<commit_before>pub mod basic_particle;
pub use self::basic_particle::*;

extern crate num;
use self::num::Float;
use super::vector::*;

///An object that has quanta
pub trait Quanta<D> {
    //Retrieve the quanta of a physics particle.
    fn quanta(&self) -> D;
}

///An object that has inertia
pub trait Inertia<D> {
    //Retrieve the inertia of a physics particle.
    fn inertia(&self) -> D;
}

///An object that has location
pub trait Position<V> {
    //Get position of particle.
    fn position(&self) -> V;
}

///An object that has velocity
pub trait Velocity<V> {
    //Get velocity of particle.
    fn velocity(&self) -> V;
}

///An object that has a simple particle motion interface
pub trait Particle<V, D>: Position<V> + Velocity<V> + Inertia<D> {
    ///Apply force to particle, but it isn't moved forward in time until advance is called.
    ///This requires interior mutability and unsafe declarations to fulfil.
    fn impulse(&self, vec: &V);
    ///Advance particle forward in time (update position and velocity from net force).
    fn advance(&mut self, time: D);
}

///Any particle that implements the necessary traits gains access to all of the capabilities of PhysicsParticle.
pub trait PhysicsParticle<V, D>: Particle<V, D> + Quanta<D> + Inertia<D>
    where V: Vector<D>, D: Float
{
    ///Convert a PhysicsParticle into a "basic particle" that implements PhysicsParticle but has the minimum members.
    ///Use this to implement data structures that need to create intermediary particles.
    fn basic_form(&self) -> BasicParticle<V, D> {
        BasicParticle::new(self.quanta(), self.position(), self.velocity(), self.inertia())
    }

    ///Apply drag forces to a particle.
    fn drag(&self, magnitude: D) {
        let force = -self.velocity() * magnitude;
        self.impulse(&force);
    }

    ///Apply proper attraction to a single physics particle towards a location and with a magnitude.
    fn gravitate_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        //Create delta vector from the particle to the center of attraction.
        let delta = center.position() - self.position();
        let distance = delta.displacement();
        let force = delta / distance.powi(3) * magnitude * self.quanta() * center.quanta();
        self.impulse(&force);
    }

    ///This works the same as gravitate_radius_squared and gravitate_to.
    fn gravitate_radius_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V> + Ball<D>
    {
        //Create delta vector from the particle to the center of attraction.
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = delta * magnitude * self.quanta() * center.quanta() /
            if distance_squared > center.radius().powi(2) {
                distance_squared.sqrt().powi(3)
            } else {
                center.radius().powi(2)
            };
        self.impulse(&force);
    }

    ///Apply spring forces between one particle and a virtual particle that is unaffected.
    fn hooke_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        let delta = center.position() - self.position();
        let mag = delta.displacement();
        if mag.is_normal() {
            let force = delta / mag * delta.displacement() *
                magnitude * self.quanta() * center.quanta();
            self.impulse(&force);
        }
    }

    ///Apply spring forces between one particle and a virtual particle that is unaffected.
    fn hooke_equilibrium_to<T: ?Sized>(&self, center: &T, equilibrium: D, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        let delta = center.position() - self.position();
        let force = delta.normalized() * (delta.displacement() - equilibrium) *
            magnitude * self.quanta() * center.quanta();
        self.impulse(&force);
    }

    ///Apply lorentz force to a particle in a field given by a vector with the magnitude and direction of the field.
    fn lorentz_field(&self, field: &V)
        where V: CrossVector
    {
        let force = V::cross(&self.velocity(), field) * self.quanta() / self.inertia();
        self.impulse(&force);
    }

    ///Apply the lorentz force on a virtual particle that is unaffected.
    fn lorentz_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where V: CrossVector, T: Quanta<D> + Position<V> + Velocity<V>
    {
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = V::cross(&V::cross(&self.velocity(), &delta), &center.velocity()) * magnitude *
            self.quanta() * center.quanta() / distance_squared.sqrt().powi(3);

        self.impulse(&force);
    }

    ///Apply the lorentz force on a virtual particle that is unaffected.
    fn lorentz_radius_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where V: CrossVector, T: Quanta<D> + Position<V> + Velocity<V> + Ball<D>
    {
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = V::cross(&V::cross(&self.velocity(), &delta), &center.velocity()) * magnitude *
            self.quanta() * center.quanta() /
            if distance_squared > center.radius().powi(2) {
                distance_squared.sqrt().powi(3)
            } else {
                center.radius().powi(2)
            };

        self.impulse(&force);
    }
}

///Apply proper attraction between two physics particles based on their quanta and position.
pub fn gravitate<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    //Create delta vector between the two positions.
    let delta = rhs.position() - lhs.position();
    //Find the distance of the delta vector.
    let distance = delta.displacement();
    //Dividing the delta vector by the distance cubed computes attractive force as per the inverse square law.
    //The extra degree normalizes the direction vector to a unit vector.
    let force = delta * magnitude / distance.powi(3) *
    //Multiply by the two quanta of the objects to compute the final force.
    lhs.quanta() * rhs.quanta();

    //Force lhs in the direction of force.
    lhs.impulse(&force);
    //Apply the inverse force to the rhs similarly.
    rhs.impulse(&-force);
}

#[test]
fn gravitate_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    gravitate(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///If gravitating at a distance greater than the net radius, then gravitational interaction is applied as if the
///particles are point particles. If the distance is less than the radius, then the interaction happens as if the
///gravitational quanta (mass) is evenly distributed and gravitational flux is used instead, which causes the
///interaction to become proportional to the radius, meaning that as the radius approaches zero, so does the force.
pub fn gravitate_radius<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D> + Ball<D>, T2: PhysicsParticle<V, D> + Ball<D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let radius_squared = (lhs.radius() + rhs.radius()).powi(2);
    //Force is the only thing that changes from normal gravitation.
    let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
        distance_squared.sqrt().powi(3)
    } else {
        radius_squared
    };
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///This is the same as the radius function, but the sum of the radii squared is passed separately to avoid overhead.
pub fn gravitate_radius_squared<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, radius_squared: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    //Force is the only thing that changes from normal gravitation.
    let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
        distance_squared.sqrt().powi(3)
    } else {
        radius_squared
    };
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///Apply spring forces between two particles.
pub fn hooke<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let force = delta.normalized() * magnitude * delta.displacement() * lhs.quanta() * rhs.quanta();
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

#[test]
fn hooke_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    hooke(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///Apply spring forces between two particles with specified equilibrium distance.
pub fn hooke_equilibrium<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, equilibrium: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let force = delta.normalized() * magnitude *
        //We scale such that if displacement is greater than equilibrium, the particles attract proportionally.
        //Particles with a displacement smaller than equilibrium repel each other.
        (delta.displacement() - equilibrium) *
        lhs.quanta() * rhs.quanta();
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///Apply lorentz forces between two PhysicsParticle objects based on quanta, position, and velocity.
pub fn lorentz<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance = delta.displacement();
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) *
        lhs.quanta() * rhs.quanta() / distance.powi(3) * magnitude;

    lhs.impulse(&-force);
    rhs.impulse(&force);
}

#[test]
fn lorentz_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    lorentz(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///Apply lorentz forces between two PhysicsParticle + Ball objects assuming uniformly distributed quanta.
pub fn lorentz_radius<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D> + Ball<D>, T2: PhysicsParticle<V, D> + Ball<D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let radius_squared = (lhs.radius() + rhs.radius()).powi(2);
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
        lhs.quanta() * rhs.quanta() /
        if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };

    lhs.impulse(&-force);
    rhs.impulse(&force);
}

///Apply lorentz forces between two PhysicsParticle objects using a precomputed net radius.
pub fn lorentz_radius_squared<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, radius_squared: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
        lhs.quanta() * rhs.quanta() /
        if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };

    lhs.impulse(&-force);
    rhs.impulse(&force);
}
<commit_msg>apply fix to all functions<commit_after>pub mod basic_particle;
pub use self::basic_particle::*;

extern crate num;
use self::num::Float;
use super::vector::*;

///An object that has quanta
pub trait Quanta<D> {
    //Retrieve the quanta of a physics particle.
    fn quanta(&self) -> D;
}

///An object that has inertia
pub trait Inertia<D> {
    //Retrieve the inertia of a physics particle.
    fn inertia(&self) -> D;
}

///An object that has location
pub trait Position<V> {
    //Get position of particle.
    fn position(&self) -> V;
}

///An object that has velocity
pub trait Velocity<V> {
    //Get velocity of particle.
    fn velocity(&self) -> V;
}

///An object that has a simple particle motion interface
pub trait Particle<V, D>: Position<V> + Velocity<V> + Inertia<D> {
    ///Apply force to particle, but it isn't moved forward in time until advance is called.
    ///This requires interior mutability and unsafe declarations to fulfil.
    fn impulse(&self, vec: &V);
    ///Advance particle forward in time (update position and velocity from net force).
    fn advance(&mut self, time: D);
}

///Any particle that implements the necessary traits gains access to all of the capabilities of PhysicsParticle.
pub trait PhysicsParticle<V, D>: Particle<V, D> + Quanta<D> + Inertia<D>
    where V: Vector<D>, D: Float
{
    ///Convert a PhysicsParticle into a "basic particle" that implements PhysicsParticle but has the minimum members.
    ///Use this to implement data structures that need to create intermediary particles.
    fn basic_form(&self) -> BasicParticle<V, D> {
        BasicParticle::new(self.quanta(), self.position(), self.velocity(), self.inertia())
    }

    ///Apply drag forces to a particle.
    fn drag(&self, magnitude: D) {
        let force = -self.velocity() * magnitude;
        self.impulse(&force);
    }

    ///Apply proper attraction to a single physics particle towards a location and with a magnitude.
    fn gravitate_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        //Create delta vector from the particle to the center of attraction.
        let delta = center.position() - self.position();
        let distance = delta.displacement();
        if distance.is_normal() {
            let force = delta / distance.powi(3) * magnitude * self.quanta() * center.quanta();
            self.impulse(&force);
        }
    }

    ///This works the same as gravitate_radius_squared and gravitate_to.
    fn gravitate_radius_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V> + Ball<D>
    {
        //Create delta vector from the particle to the center of attraction.
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        if distance_squared.is_normal() {
            let force = delta * magnitude * self.quanta() * center.quanta() /
                if distance_squared > center.radius().powi(2) {
                    distance_squared.sqrt().powi(3)
                } else {
                    center.radius().powi(2)
                };
            self.impulse(&force);
        }
    }

    ///Apply spring forces between one particle and a virtual particle that is unaffected.
    fn hooke_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        let delta = center.position() - self.position();
        let force = delta * magnitude * self.quanta() * center.quanta();
        self.impulse(&force);
    }

    ///Apply spring forces between one particle and a virtual particle that is unaffected.
    fn hooke_equilibrium_to<T: ?Sized>(&self, center: &T, equilibrium: D, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        let delta = center.position() - self.position();
        let displace = delta.displacement();
        if displace.is_normal() {
            let force = delta / displace * (displace - equilibrium) *
                magnitude * self.quanta() * center.quanta();
            self.impulse(&force);
        }
    }

    ///Apply lorentz force to a particle in a field given by a vector with the magnitude and direction of the field.
    fn lorentz_field(&self, field: &V)
        where V: CrossVector
    {
        let force = V::cross(&self.velocity(), field) * self.quanta() / self.inertia();
        self.impulse(&force);
    }

    ///Apply the lorentz force on a virtual particle that is unaffected.
    fn lorentz_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where V: CrossVector, T: Quanta<D> + Position<V> + Velocity<V>
    {
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        if distance_squared.is_normal() {
            let force = V::cross(&V::cross(&self.velocity(), &delta), &center.velocity()) * magnitude *
                self.quanta() * center.quanta() / distance_squared.sqrt().powi(3);

            self.impulse(&force);
        }
    }

    ///Apply the lorentz force on a virtual particle that is unaffected.
    fn lorentz_radius_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where V: CrossVector, T: Quanta<D> + Position<V> + Velocity<V> + Ball<D>
    {
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        if distance_squared.is_normal() {
            let force = V::cross(&V::cross(&self.velocity(), &delta), &center.velocity()) * magnitude *
                self.quanta() * center.quanta() /
                if distance_squared > center.radius().powi(2) {
                    distance_squared.sqrt().powi(3)
                } else {
                    center.radius().powi(2)
                };

            self.impulse(&force);
        }
    }
}

///Apply proper attraction between two physics particles based on their quanta and position.
pub fn gravitate<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    //Create delta vector between the two positions.
    let delta = rhs.position() - lhs.position();
    //Find the distance of the delta vector.
    let distance = delta.displacement();
    if distance.is_normal() {
        //Dividing the delta vector by the distance cubed computes attractive force as per the inverse square law.
        //The extra degree normalizes the direction vector to a unit vector.
        let force = delta * magnitude / distance.powi(3) *
        //Multiply by the two quanta of the objects to compute the final force.
        lhs.quanta() * rhs.quanta();

        //Force lhs in the direction of force.
        lhs.impulse(&force);
        //Apply the inverse force to the rhs similarly.
        rhs.impulse(&-force);
    }
}

#[test]
fn gravitate_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    gravitate(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///If gravitating at a distance greater than the net radius, then gravitational interaction is applied as if the
///particles are point particles. If the distance is less than the radius, then the interaction happens as if the
///gravitational quanta (mass) is evenly distributed and gravitational flux is used instead, which causes the
///interaction to become proportional to the radius, meaning that as the radius approaches zero, so does the force.
pub fn gravitate_radius<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D> + Ball<D>, T2: PhysicsParticle<V, D> + Ball<D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    if distance_squared.is_normal() {
        let radius_squared = (lhs.radius() + rhs.radius()).powi(2);
        //Force is the only thing that changes from normal gravitation.
        let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };
        lhs.impulse(&force);
        rhs.impulse(&-force);
    }
}

///This is the same as the radius function, but the sum of the radii squared is passed separately to avoid overhead.
pub fn gravitate_radius_squared<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, radius_squared: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    if distance_squared.is_normal() {
        //Force is the only thing that changes from normal gravitation.
        let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };
        lhs.impulse(&force);
        rhs.impulse(&-force);
    }
}

///Apply spring forces between two particles.
pub fn hooke<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let force = delta * magnitude * lhs.quanta() * rhs.quanta();
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

#[test]
fn hooke_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    hooke(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///Apply spring forces between two particles with specified equilibrium distance.
pub fn hooke_equilibrium<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, equilibrium: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let displace = delta.displacement();
    if displace.is_normal() {
        let force = delta / displace * magnitude *
            //We scale such that if displacement is greater than equilibrium, the particles attract proportionally.
            //Particles with a displacement smaller than equilibrium repel each other.
            (displace - equilibrium) *
            lhs.quanta() * rhs.quanta();
        lhs.impulse(&force);
        rhs.impulse(&-force);
    }
}

///Apply lorentz forces between two PhysicsParticle objects based on quanta, position, and velocity.
pub fn lorentz<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance = delta.displacement();
    if distance.is_normal() {
        let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) *
            lhs.quanta() * rhs.quanta() / distance.powi(3) * magnitude;

        lhs.impulse(&-force);
        rhs.impulse(&force);
    }
}

#[test]
fn lorentz_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    lorentz(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///Apply lorentz forces between two PhysicsParticle + Ball objects assuming uniformly distributed quanta.
pub fn lorentz_radius<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D> + Ball<D>, T2: PhysicsParticle<V, D> + Ball<D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    if distance_squared.is_normal() {
        let radius_squared = (lhs.radius() + rhs.radius()).powi(2);
        let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
            lhs.quanta() * rhs.quanta() /
            if distance_squared > radius_squared {
                distance_squared.sqrt().powi(3)
            } else {
                radius_squared
            };

        lhs.impulse(&-force);
        rhs.impulse(&force);
    }
}

///Apply lorentz forces between two PhysicsParticle objects using a precomputed net radius.
pub fn lorentz_radius_squared<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, radius_squared: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    if distance_squared.is_normal() {
        let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
            lhs.quanta() * rhs.quanta() /
            if distance_squared > radius_squared {
                distance_squared.sqrt().powi(3)
            } else {
                radius_squared
            };

        lhs.impulse(&-force);
        rhs.impulse(&force);
    }
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Cerberus protocol messages.
//!
//! A Cerberus protocol message (also called a "command") consists of three
//! parts:
//! - A *command type*, representing the type of command this is.
//! - A *request bit*, indicating whether this message is a request or a
//!   response.
//! - A *body*, which is a buffer that is interpreted according to the
//!   command type.
//!
//! There is also a special "error" response, with no corresponding request,
//! which is used both to indicate an error, and as an ACK-type response for
//! requests that do not otherwise have data to respond with.
//!
//! This module provides a way to convert a parsed `manticore` header
//! (consisting, at minimum, of a command type and a request bit) and a buffer
//! into a request or response, and, also, to reverse that process.
//!
//! If a message type contains a large buffer, the message type will have an
//! appropriate lifetime attached to it.
//!
//! In addition to providing (de)serialization to and from the Cerberus wire
//! format (via the [`wire` module]), the `serde` feature will provide relevant
//! implementations of [`serde`] traits, for (de)serialization to and from
//! human-readable formats, like JSON.
//!
//! ---
//!
//! This module provides a subset of required and optional commands specified
//! by Cerberus. In particular, `manticore` does not yet implement
//! authentication or secure channel negotiation.
//!
//! `manticore` also provides some additional protocol messages not specified
//! by Cerberus, encoded using command type bytes not allocated by Cerberus.
//!
//! Also, unlike Cerberus, `manticore` does not require that a session be
//! spoken over MCTP, and, as such, does not use the same header as Cerberus.
//!
//! [`wire` module]: wire/index.html
//! [`serde`]: https://serde.rs

// This is required due to the make_fuzz_safe! macro.
#![allow(unused_parens)]

use crate::io::Read;
use crate::io::Write;
use crate::mem::Arena;
use crate::protocol::wire::FromWire;
use crate::protocol::wire::FromWireError;
use crate::protocol::wire::ToWire;
use crate::protocol::wire::ToWireError;

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

#[macro_use]
mod macros;
#[cfg(feature = "arbitrary-derive")]
pub use macros::FuzzSafe;

#[macro_use]
pub mod wire;

pub mod device_id;
pub use device_id::DeviceId;

pub mod device_info;
pub use device_info::DeviceInfo;

pub mod device_uptime;
pub use device_uptime::DeviceUptime;

pub mod capabilities;
pub use capabilities::DeviceCapabilities;

pub mod firmware_version;
pub use firmware_version::FirmwareVersion;

pub mod reset_counter;
pub use reset_counter::ResetCounter;

pub mod request_counter;
pub use request_counter::RequestCounter;

/// A Cerberus command.
///
/// A Cerberus command is identified by two types, each of which has a
/// corresponding [`CommandType`]:
/// - A unique request type.
/// - A response type, which may be [`Error`].
///
/// This trait is not implemented by any of the request or response types, but
/// is intead implemented by uninhabited types that represent pairs of requests
/// and responses, for use in generic programming.
///
/// [`CommandType`]: enum.CommandType.html
/// [`Error`]: struct.Error.html
pub trait Command<'req> {
    /// The unique request type for this `Command`.
    type Req: Request<'req>;
    /// The response type for this `Command`, which will either be unique or
    /// [`Error`].
    ///
    /// [`Error`]: struct.Error.html
    type Resp: Response<'req>;
}

/// A Cerberus request.
///
/// See [`Command`](trait.Command.html).
pub trait Request<'req>: FromWire<'req> + ToWire {
    /// The unique [`CommandType`] for this `Request`.
    ///
    /// [`CommandType`]: enum.CommandType.html
    const TYPE: CommandType;
}

/// A Cerberus response.
///
/// See [`Command`](trait.Command.html).
pub trait Response<'req>: FromWire<'req> + ToWire {
    /// The unique [`CommandType`] for this `Response`.
    ///
    /// [`CommandType`]: enum.CommandType.html
    const TYPE: CommandType;
}

wire_enum! {
    /// A Cerberus command type.
    ///
    /// This enum represents all command types implemented by `manticore`,
    /// including any `manticore`-specific messages not defined by Cerberus.
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum CommandType: u8 {
        /// An error message (or a trivial command ACK).
        ///
        /// See [`Error`](struct.Error.html).
        Error = 0x7f,
        /// A request for the RoT's firmware version.
        ///
        /// See [`FirmwareVersion`].
        ///
        /// [`FirmwareVersion`]:
        ///     firmware_version/struct.FirmwareVersion.html
        FirmwareVersion = 0x01,
        /// A request to negotiate device capabilities.
        ///
        /// See [`DeviceCapabilities`].
        ///
        /// [`DeviceCapabilities`]:
        ///     capabilites/struct.DeviceCapabilities.html
        DeviceCapabilities = 0x02,
        /// A request for this device's identity.
        ///
        /// See [`DeviceId`].
        ///
        /// [`DeviceId`]:
        ///     device_id/struct.DeviceId.html
        DeviceId = 0x03,
        /// A request for information about this device.
        ///
        /// See [`DeviceInfo`].
        ///
        /// [`DeviceInfo`]:
        ///     device_info/struct.DeviceInfo.html
        DeviceInfo = 0x04,
        /// A request for the number of times the device has been reset since
        /// POR.
        ///
        /// See [`ResetCounter`].
        ///
        /// [`ResetCounter`]:
        ///     reset_counter/struct.ResetCounter.html
        ResetCounter = 0x87,
        /// A request for the uptime of the device since last reset.
        ///
        /// Note that this command is a `manticore` extension.
        ///
        /// See [`DeviceUptime`].
        ///
        /// [`DeviceUptime`]:
        ///     device_uptime/struct.DeviceUptime.html
        DeviceUptime = 0xa0,
        /// A request for an approximate number of requests the device has
        /// handled since last reset.
        ///
        /// Note that this command is a `manticore` extension.
        ///
        /// See [`RequestCounter`].
        ///
        /// [`RequestCounter`]:
        ///     device_uptime/struct.RequestCounter.html
        RequestCounter = 0xa1,
    }
}

impl CommandType {
    /// Returns `true` when `self` represents a `manticore` extension to the
    /// protocol.
    pub fn is_manticore_extension(self) -> bool {
        matches!(self, Self::DeviceUptime)
    }
}

/// A parsed `manticore` header.
///
/// This struct represents all of the meaningful fields from a `manticore`
/// header; the actual format of the header is left up to an integration of
/// this library.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Header {
    /// The [`CommandType`] for a request.
    ///
    /// [`CommandType`]: enum.CommandType.html
    pub command: CommandType,
    /// The "request bit", for interpreting whether the body is the
    /// request or response variant of a command.
    pub is_request: bool,
}

/// The length of a `manticore` header on the wire, in bytes.
pub const HEADER_LEN: usize = 5;

/// A magic number required at the start of each `manticore` header.
const HEADER_MAGIC: &[u8] = &[0b01111110, 0x14, 0x14];

impl<'a> FromWire<'a> for Header {
    fn from_wire<R: Read, A: Arena>(
        mut r: R,
        a: &'a A,
    ) -> Result<Self, FromWireError> {
        let mut magic = [0; 3];
        r.read_bytes(&mut magic)?;
        if magic != HEADER_MAGIC {
            return Err(FromWireError::OutOfRange);
        }

        let request_byte = r.read_le::<u8>()?;
        let is_request = match request_byte {
            0b0000_0000 => false,
            0b1000_0000 => true,
            _ => return Err(FromWireError::OutOfRange),
        };

        let command = CommandType::from_wire(r, a)?;
        Ok(Self {
            is_request,
            command,
        })
    }
}

impl ToWire for Header {
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), ToWireError> {
        w.write_bytes(HEADER_MAGIC)?;
        w.write_le((self.is_request as u8) << 7)?;
        self.command.to_wire(w)?;
        Ok(())
    }
}

wire_enum! {
    /// A Cerberus error.
    ///
    /// This enum represents all error types implemented by `manticore`.
    /// Because `manticore` does not mandate running the connection over MCTP,
    /// the MCTP-specific error codes are omited.
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum ErrorCode: u8 {
        /// Represents a successful operation; this "error" code is used to
        /// turn an [`Error`] into an ACK.
        ///
        /// [`Error`]: struct.Error.html
        Ok = 0x00,
        /// Indicates that the device is "busy", usually meaning that other
        /// commands are being serviced.
        Busy = 0x03,
        /// Indicates an unspecified, vendor-defined error, which may include
        /// extra data in an [`Error`].
        ///
        /// [`Error`]: struct.Error.html
        Unspecified = 0x04,
    }
}

/// A generic error response.
///
/// This message is used to indicate that a request resulted in an error, or
/// as an ACK for commands that otherwise have no response message.
///
/// This command corresponds to [`CommandType::Error`] and does not have a
/// request counterpart.
///
/// [`CommandType::Error`]: enum.CommandType.html#variant.Error
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Error {
    /// What kind of error this is (or, it's merely an ACK).
    pub code: ErrorCode,
    /// A fixed array of "extra data" that can come with an error code.
    pub data: [u8; 4],
}

impl Error {
    /// Creates an "ACK" response, consisting of an `Error` with an
    /// [`ErrorCode::Ok`] code.
    ///
    /// [`ErrorCode::Ok`]: enum.ErrorCode.html#variant.Ok
    pub fn new_ack() -> Self {
        Self {
            code: ErrorCode::Ok,
            data: [0; 4],
        }
    }
}

impl Response<'_> for Error {
    const TYPE: CommandType = CommandType::Error;
}

impl<'a> FromWire<'a> for Error {
    fn from_wire<R: Read, A: Arena>(
        mut r: R,
        a: &'a A,
    ) -> Result<Self, FromWireError> {
        let code = ErrorCode::from_wire(&mut r, a)?;
        let mut data = [0; 4];
        r.read_bytes(&mut data)?;

        Ok(Self { code, data })
    }
}

impl ToWire for Error {
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), ToWireError> {
        self.code.to_wire(&mut w)?;
        w.write_bytes(&self.data[..])?;
        Ok(())
    }
}
<commit_msg>protocol: Allow converting u8 to ComandType<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Cerberus protocol messages.
//!
//! A Cerberus protocol message (also called a "command") consists of three
//! parts:
//! - A *command type*, representing the type of command this is.
//! - A *request bit*, indicating whether this message is a request or a
//!   response.
//! - A *body*, which is a buffer that is interpreted according to the
//!   command type.
//!
//! There is also a special "error" response, with no corresponding request,
//! which is used both to indicate an error, and as an ACK-type response for
//! requests that do not otherwise have data to respond with.
//!
//! This module provides a way to convert a parsed `manticore` header
//! (consisting, at minimum, of a command type and a request bit) and a buffer
//! into a request or response, and, also, to reverse that process.
//!
//! If a message type contains a large buffer, the message type will have an
//! appropriate lifetime attached to it.
//!
//! In addition to providing (de)serialization to and from the Cerberus wire
//! format (via the [`wire` module]), the `serde` feature will provide relevant
//! implementations of [`serde`] traits, for (de)serialization to and from
//! human-readable formats, like JSON.
//!
//! ---
//!
//! This module provides a subset of required and optional commands specified
//! by Cerberus. In particular, `manticore` does not yet implement
//! authentication or secure channel negotiation.
//!
//! `manticore` also provides some additional protocol messages not specified
//! by Cerberus, encoded using command type bytes not allocated by Cerberus.
//!
//! Also, unlike Cerberus, `manticore` does not require that a session be
//! spoken over MCTP, and, as such, does not use the same header as Cerberus.
//!
//! [`wire` module]: wire/index.html
//! [`serde`]: https://serde.rs

// This is required due to the make_fuzz_safe! macro.
#![allow(unused_parens)]

use crate::io::Read;
use crate::io::Write;
use crate::mem::Arena;
use crate::protocol::wire::FromWire;
use crate::protocol::wire::FromWireError;
use crate::protocol::wire::ToWire;
use crate::protocol::wire::ToWireError;

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

#[macro_use]
mod macros;
#[cfg(feature = "arbitrary-derive")]
pub use macros::FuzzSafe;

#[macro_use]
pub mod wire;

pub mod device_id;
pub use device_id::DeviceId;

pub mod device_info;
pub use device_info::DeviceInfo;

pub mod device_uptime;
pub use device_uptime::DeviceUptime;

pub mod capabilities;
pub use capabilities::DeviceCapabilities;

pub mod firmware_version;
pub use firmware_version::FirmwareVersion;

pub mod reset_counter;
pub use reset_counter::ResetCounter;

pub mod request_counter;
pub use request_counter::RequestCounter;

/// A Cerberus command.
///
/// A Cerberus command is identified by two types, each of which has a
/// corresponding [`CommandType`]:
/// - A unique request type.
/// - A response type, which may be [`Error`].
///
/// This trait is not implemented by any of the request or response types, but
/// is intead implemented by uninhabited types that represent pairs of requests
/// and responses, for use in generic programming.
///
/// [`CommandType`]: enum.CommandType.html
/// [`Error`]: struct.Error.html
pub trait Command<'req> {
    /// The unique request type for this `Command`.
    type Req: Request<'req>;
    /// The response type for this `Command`, which will either be unique or
    /// [`Error`].
    ///
    /// [`Error`]: struct.Error.html
    type Resp: Response<'req>;
}

/// A Cerberus request.
///
/// See [`Command`](trait.Command.html).
pub trait Request<'req>: FromWire<'req> + ToWire {
    /// The unique [`CommandType`] for this `Request`.
    ///
    /// [`CommandType`]: enum.CommandType.html
    const TYPE: CommandType;
}

/// A Cerberus response.
///
/// See [`Command`](trait.Command.html).
pub trait Response<'req>: FromWire<'req> + ToWire {
    /// The unique [`CommandType`] for this `Response`.
    ///
    /// [`CommandType`]: enum.CommandType.html
    const TYPE: CommandType;
}

wire_enum! {
    /// A Cerberus command type.
    ///
    /// This enum represents all command types implemented by `manticore`,
    /// including any `manticore`-specific messages not defined by Cerberus.
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum CommandType: u8 {
        /// An error message (or a trivial command ACK).
        ///
        /// See [`Error`](struct.Error.html).
        Error = 0x7f,
        /// A request for the RoT's firmware version.
        ///
        /// See [`FirmwareVersion`].
        ///
        /// [`FirmwareVersion`]:
        ///     firmware_version/struct.FirmwareVersion.html
        FirmwareVersion = 0x01,
        /// A request to negotiate device capabilities.
        ///
        /// See [`DeviceCapabilities`].
        ///
        /// [`DeviceCapabilities`]:
        ///     capabilites/struct.DeviceCapabilities.html
        DeviceCapabilities = 0x02,
        /// A request for this device's identity.
        ///
        /// See [`DeviceId`].
        ///
        /// [`DeviceId`]:
        ///     device_id/struct.DeviceId.html
        DeviceId = 0x03,
        /// A request for information about this device.
        ///
        /// See [`DeviceInfo`].
        ///
        /// [`DeviceInfo`]:
        ///     device_info/struct.DeviceInfo.html
        DeviceInfo = 0x04,
        /// A request for the number of times the device has been reset since
        /// POR.
        ///
        /// See [`ResetCounter`].
        ///
        /// [`ResetCounter`]:
        ///     reset_counter/struct.ResetCounter.html
        ResetCounter = 0x87,
        /// A request for the uptime of the device since last reset.
        ///
        /// Note that this command is a `manticore` extension.
        ///
        /// See [`DeviceUptime`].
        ///
        /// [`DeviceUptime`]:
        ///     device_uptime/struct.DeviceUptime.html
        DeviceUptime = 0xa0,
        /// A request for an approximate number of requests the device has
        /// handled since last reset.
        ///
        /// Note that this command is a `manticore` extension.
        ///
        /// See [`RequestCounter`].
        ///
        /// [`RequestCounter`]:
        ///     device_uptime/struct.RequestCounter.html
        RequestCounter = 0xa1,
    }
}

impl CommandType {
    /// Returns `true` when `self` represents a `manticore` extension to the
    /// protocol.
    pub fn is_manticore_extension(self) -> bool {
        matches!(self, Self::DeviceUptime)
    }
}

impl From<u8> for CommandType {
    fn from(num: u8) -> CommandType {
        match num {
            0x01 => CommandType::FirmwareVersion,
            0x02 => CommandType::DeviceCapabilities,
            0x03 => CommandType::DeviceId,
            0x04 => CommandType::DeviceInfo,
            0x87 => CommandType::ResetCounter,
            0xa0 => CommandType::DeviceUptime,
            0xa1 => CommandType::RequestCounter,
            _ => CommandType::Error,
        }
    }
}

/// A parsed `manticore` header.
///
/// This struct represents all of the meaningful fields from a `manticore`
/// header; the actual format of the header is left up to an integration of
/// this library.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Header {
    /// The [`CommandType`] for a request.
    ///
    /// [`CommandType`]: enum.CommandType.html
    pub command: CommandType,
    /// The "request bit", for interpreting whether the body is the
    /// request or response variant of a command.
    pub is_request: bool,
}

/// The length of a `manticore` header on the wire, in bytes.
pub const HEADER_LEN: usize = 5;

/// A magic number required at the start of each `manticore` header.
const HEADER_MAGIC: &[u8] = &[0b01111110, 0x14, 0x14];

impl<'a> FromWire<'a> for Header {
    fn from_wire<R: Read, A: Arena>(
        mut r: R,
        a: &'a A,
    ) -> Result<Self, FromWireError> {
        let mut magic = [0; 3];
        r.read_bytes(&mut magic)?;
        if magic != HEADER_MAGIC {
            return Err(FromWireError::OutOfRange);
        }

        let request_byte = r.read_le::<u8>()?;
        let is_request = match request_byte {
            0b0000_0000 => false,
            0b1000_0000 => true,
            _ => return Err(FromWireError::OutOfRange),
        };

        let command = CommandType::from_wire(r, a)?;
        Ok(Self {
            is_request,
            command,
        })
    }
}

impl ToWire for Header {
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), ToWireError> {
        w.write_bytes(HEADER_MAGIC)?;
        w.write_le((self.is_request as u8) << 7)?;
        self.command.to_wire(w)?;
        Ok(())
    }
}

wire_enum! {
    /// A Cerberus error.
    ///
    /// This enum represents all error types implemented by `manticore`.
    /// Because `manticore` does not mandate running the connection over MCTP,
    /// the MCTP-specific error codes are omited.
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum ErrorCode: u8 {
        /// Represents a successful operation; this "error" code is used to
        /// turn an [`Error`] into an ACK.
        ///
        /// [`Error`]: struct.Error.html
        Ok = 0x00,
        /// Indicates that the device is "busy", usually meaning that other
        /// commands are being serviced.
        Busy = 0x03,
        /// Indicates an unspecified, vendor-defined error, which may include
        /// extra data in an [`Error`].
        ///
        /// [`Error`]: struct.Error.html
        Unspecified = 0x04,
    }
}

/// A generic error response.
///
/// This message is used to indicate that a request resulted in an error, or
/// as an ACK for commands that otherwise have no response message.
///
/// This command corresponds to [`CommandType::Error`] and does not have a
/// request counterpart.
///
/// [`CommandType::Error`]: enum.CommandType.html#variant.Error
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Error {
    /// What kind of error this is (or, it's merely an ACK).
    pub code: ErrorCode,
    /// A fixed array of "extra data" that can come with an error code.
    pub data: [u8; 4],
}

impl Error {
    /// Creates an "ACK" response, consisting of an `Error` with an
    /// [`ErrorCode::Ok`] code.
    ///
    /// [`ErrorCode::Ok`]: enum.ErrorCode.html#variant.Ok
    pub fn new_ack() -> Self {
        Self {
            code: ErrorCode::Ok,
            data: [0; 4],
        }
    }
}

impl Response<'_> for Error {
    const TYPE: CommandType = CommandType::Error;
}

impl<'a> FromWire<'a> for Error {
    fn from_wire<R: Read, A: Arena>(
        mut r: R,
        a: &'a A,
    ) -> Result<Self, FromWireError> {
        let code = ErrorCode::from_wire(&mut r, a)?;
        let mut data = [0; 4];
        r.read_bytes(&mut data)?;

        Ok(Self { code, data })
    }
}

impl ToWire for Error {
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), ToWireError> {
        self.code.to_wire(&mut w)?;
        w.write_bytes(&self.data[..])?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2016 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::error::Error;
use std::fmt;
use std::str::FromStr;

#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

/// The number of bytes in an ethernet (MAC) address.
pub const ETHER_ADDR_LEN: usize = 6;

/// Structure of a 48-bit Ethernet address.
type EtherAddr = [u8; ETHER_ADDR_LEN];

const LOCAL_ADDR_BIT: u8 = 0x02;
const MULTICAST_ADDR_BIT: u8 = 0x01;

/// A MAC address.
#[derive(PartialEq, Eq, Clone, Copy, Default, Hash, Ord, PartialOrd)]
pub struct MacAddr(pub u8, pub u8, pub u8, pub u8, pub u8, pub u8);

impl MacAddr {
    /// Construct a new `MacAddr` instance.
    pub fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> MacAddr {
        MacAddr(a, b, c, d, e, f)
    }

    /// Construct an all-zero `MacAddr` instance.
    pub fn zero() -> MacAddr {
        Default::default()
    }

    /// Construct a broadcast `MacAddr` instance.
    pub fn broadcast() -> MacAddr {
        [0xff; ETHER_ADDR_LEN].into()
    }

    /// Returns true if a `MacAddr` is an all-zero address.
    pub fn is_zero(&self) -> bool {
        *self == Self::zero()
    }

    /// Returns true if the MacAddr is a universally administered addresses (UAA).
    pub fn is_universal(&self) -> bool {
        !self.is_local()
    }

    /// Returns true if the MacAddr is a locally administered addresses (LAA).
    pub fn is_local(&self) -> bool {
        (self.0 & LOCAL_ADDR_BIT) == LOCAL_ADDR_BIT
    }

    /// Returns true if the MacAddr is a unicast address.
    pub fn is_unicast(&self) -> bool {
        !self.is_multicast()
    }

    /// Returns true if the MacAddr is a multicast address.
    pub fn is_multicast(&self) -> bool {
        (self.0 & MULTICAST_ADDR_BIT) == MULTICAST_ADDR_BIT
    }

    /// Returns true if the MacAddr is a broadcast address.
    pub fn is_broadcast(&self) -> bool {
        *self == Self::broadcast()
    }
}

impl From<EtherAddr> for MacAddr {
    fn from(addr: EtherAddr) -> MacAddr {
        MacAddr(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
    }
}

impl From<MacAddr> for EtherAddr {
    fn from(addr: MacAddr) -> Self {
        [addr.0, addr.1, addr.2, addr.3, addr.4, addr.5]
    }
}

impl PartialEq<EtherAddr> for MacAddr {
    fn eq(&self, other: &EtherAddr) -> bool {
        *self == MacAddr::from(*other)
    }
}

impl fmt::Display for MacAddr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(
            fmt,
            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
            self.0, self.1, self.2, self.3, self.4, self.5
        )
    }
}

#[cfg(feature = "serde")]
impl Serialize for MacAddr {
    /// Serializes the MAC address.
    ///
    /// It serializes either to a string or its binary representation, depending on what the format
    /// prefers.
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        if serializer.is_human_readable() {
            serializer.serialize_str(&format!("{}", self))
        } else {
            serializer.serialize_bytes(&[self.0, self.1, self.2, self.3, self.4, self.5])
        }
    }
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for MacAddr {
    /// Deserializes the MAC address.
    ///
    /// It deserializes it from either a byte array (of size 6) or a string. If the format is
    /// self-descriptive (like JSON or MessagePack), it auto-detects it. If not, it obeys the
    /// human-readable property of the deserializer.
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        struct MacAddrVisitor;
        impl<'de> de::Visitor<'de> for MacAddrVisitor {
            type Value = MacAddr;

            fn visit_str<E: de::Error>(self, value: &str) -> Result<MacAddr, E> {
                value.parse().map_err(|err| E::custom(&format!("{}", err)))
            }

            fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<MacAddr, E> {
                if v.len() == 6 {
                    Ok(MacAddr::new(v[0], v[1], v[2], v[3], v[4], v[5]))
                } else {
                    Err(E::invalid_length(v.len(), &self))
                }
            }

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(
                    formatter,
                    "either a string representation of a MAC address or 6-element byte array"
                )
            }
        }

        // Decide what hint to provide to the deserializer based on if it is human readable or not
        if deserializer.is_human_readable() {
            deserializer.deserialize_str(MacAddrVisitor)
        } else {
            deserializer.deserialize_bytes(MacAddrVisitor)
        }
    }
}

impl fmt::Debug for MacAddr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, fmt)
    }
}

/// Represents an error which occurred whilst parsing a MAC address.
#[derive(Copy, Debug, PartialEq, Eq, Clone)]
pub enum ParseMacAddrErr {
    /// The MAC address has too many components, eg. 00:11:22:33:44:55:66.
    TooManyComponents,
    /// The MAC address has too few components, eg. 00:11.
    TooFewComponents,
    /// One of the components contains an invalid value, eg. 00:GG:22:33:44:55.
    InvalidComponent,
}

impl Error for ParseMacAddrErr {
    fn description(&self) -> &str {
        match *self {
            ParseMacAddrErr::TooManyComponents => "Too many components in a MAC address string",
            ParseMacAddrErr::TooFewComponents => "Too few components in a MAC address string",
            ParseMacAddrErr::InvalidComponent => "Invalid component in a MAC address string",
        }
    }
}

impl fmt::Display for ParseMacAddrErr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl FromStr for MacAddr {
    type Err = ParseMacAddrErr;
    fn from_str(s: &str) -> Result<MacAddr, ParseMacAddrErr> {
        let mut parts = [0u8; 6];
        let splits = s.split(':');
        let mut i = 0;
        for split in splits {
            if i == 6 {
                return Err(ParseMacAddrErr::TooManyComponents);
            }
            match u8::from_str_radix(split, 16) {
                Ok(b) if split.len() != 0 => parts[i] = b,
                _ => return Err(ParseMacAddrErr::InvalidComponent),
            }
            i += 1;
        }

        if i == 6 {
            Ok(MacAddr(
                parts[0], parts[1], parts[2], parts[3], parts[4], parts[5],
            ))
        } else {
            Err(ParseMacAddrErr::TooFewComponents)
        }
    }
}

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

    #[test]
    fn mac_addr_from_str() {
        assert_eq!("00:00:00:00:00:00".parse(), Ok(MacAddr::zero()));
        assert_eq!("ff:ff:ff:ff:ff:ff".parse(), Ok(MacAddr::broadcast()));
        assert_eq!(
            "12:34:56:78:90:ab".parse(),
            Ok(MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB))
        );
        assert_eq!(
            "::::::".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "0::::::".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "::::0::".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "12:34:56:78".parse::<MacAddr>(),
            Err(ParseMacAddrErr::TooFewComponents)
        );
        assert_eq!(
            "12:34:56:78:".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "12:34:56:78:90".parse::<MacAddr>(),
            Err(ParseMacAddrErr::TooFewComponents)
        );
        assert_eq!(
            "12:34:56:78:90:".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "12:34:56:78:90:00:00".parse::<MacAddr>(),
            Err(ParseMacAddrErr::TooManyComponents)
        );
        assert_eq!(
            "xx:xx:xx:xx:xx:xx".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
    }

    #[test]
    fn str_from_mac_addr() {
        assert_eq!(format!("{}", MacAddr::zero()), "00:00:00:00:00:00");
        assert_eq!(format!("{}", MacAddr::broadcast()), "ff:ff:ff:ff:ff:ff");
        assert_eq!(
            format!("{}", MacAddr(0x12, 0x34, 0x56, 0x78, 0x09, 0xAB)),
            "12:34:56:78:09:ab"
        );
    }

    #[test]
    fn type_of_addr() {
        assert!(MacAddr::zero().is_zero());
        assert!(MacAddr::broadcast().is_broadcast());

        let mac = MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB);
        assert!(mac.is_local());
        assert!(mac.is_unicast());

        let mac = MacAddr(0xac, 0x87, 0xa3, 0x07, 0x32, 0xb8);
        assert!(mac.is_universal());
        assert!(mac.is_unicast());
    }

    #[test]
    fn convertion() {
        let mac = MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB);
        let addr = [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB];

        assert_eq!(mac, MacAddr::from(addr));
        assert_eq!(addr, EtherAddr::from(mac));
        assert!(mac == addr);
    }

    #[cfg(feature = "serde")]
    mod serde {
        extern crate serde_test;
        use self::serde_test::{
            assert_de_tokens, assert_de_tokens_error, assert_tokens, Compact, Configure, Readable,
            Token,
        };
        use super::*;

        #[test]
        fn string() {
            let mac = MacAddr::new(0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
            assert_tokens(&mac.readable(), &[Token::Str("11:22:33:44:55:66")]);
            assert_de_tokens(&mac.readable(), &[Token::String("11:22:33:44:55:66")]);
            assert_de_tokens(&mac.readable(), &[Token::BorrowedStr("11:22:33:44:55:66")]);
            assert_de_tokens_error::<Readable<MacAddr>>(
                &[Token::Str("not an address")],
                "Invalid component in a MAC address string",
            );
            // It still can detect bytes if provided
            assert_de_tokens(
                &mac.readable(),
                &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
            );
        }

        #[test]
        fn bytes() {
            let mac = MacAddr::new(0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
            assert_tokens(
                &mac.compact(),
                &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
            );
            assert_de_tokens(
                &mac.compact(),
                &[Token::BorrowedBytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
            );
            let err = "invalid length 2, expected either a string representation of a MAC address or 6-element byte array";
            assert_de_tokens_error::<Compact<MacAddr>>(&[Token::Bytes(&[0x11, 0x33])], err);
            let err = "invalid length 7, expected either a string representation of a MAC address or 6-element byte array";
            assert_de_tokens_error::<Compact<MacAddr>>(
                &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77])],
                err,
            );
            // Still can decode string in the compact mode
            assert_de_tokens(&mac.compact(), &[Token::Str("11:22:33:44:55:66")]);
        }
    }
}
<commit_msg>Remove deprecated `.description()` use in pnet_base<commit_after>// Copyright (c) 2014-2016 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::error::Error;
use std::fmt;
use std::str::FromStr;

#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

/// The number of bytes in an ethernet (MAC) address.
pub const ETHER_ADDR_LEN: usize = 6;

/// Structure of a 48-bit Ethernet address.
type EtherAddr = [u8; ETHER_ADDR_LEN];

const LOCAL_ADDR_BIT: u8 = 0x02;
const MULTICAST_ADDR_BIT: u8 = 0x01;

/// A MAC address.
#[derive(PartialEq, Eq, Clone, Copy, Default, Hash, Ord, PartialOrd)]
pub struct MacAddr(pub u8, pub u8, pub u8, pub u8, pub u8, pub u8);

impl MacAddr {
    /// Construct a new `MacAddr` instance.
    pub fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> MacAddr {
        MacAddr(a, b, c, d, e, f)
    }

    /// Construct an all-zero `MacAddr` instance.
    pub fn zero() -> MacAddr {
        Default::default()
    }

    /// Construct a broadcast `MacAddr` instance.
    pub fn broadcast() -> MacAddr {
        [0xff; ETHER_ADDR_LEN].into()
    }

    /// Returns true if a `MacAddr` is an all-zero address.
    pub fn is_zero(&self) -> bool {
        *self == Self::zero()
    }

    /// Returns true if the MacAddr is a universally administered addresses (UAA).
    pub fn is_universal(&self) -> bool {
        !self.is_local()
    }

    /// Returns true if the MacAddr is a locally administered addresses (LAA).
    pub fn is_local(&self) -> bool {
        (self.0 & LOCAL_ADDR_BIT) == LOCAL_ADDR_BIT
    }

    /// Returns true if the MacAddr is a unicast address.
    pub fn is_unicast(&self) -> bool {
        !self.is_multicast()
    }

    /// Returns true if the MacAddr is a multicast address.
    pub fn is_multicast(&self) -> bool {
        (self.0 & MULTICAST_ADDR_BIT) == MULTICAST_ADDR_BIT
    }

    /// Returns true if the MacAddr is a broadcast address.
    pub fn is_broadcast(&self) -> bool {
        *self == Self::broadcast()
    }
}

impl From<EtherAddr> for MacAddr {
    fn from(addr: EtherAddr) -> MacAddr {
        MacAddr(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
    }
}

impl From<MacAddr> for EtherAddr {
    fn from(addr: MacAddr) -> Self {
        [addr.0, addr.1, addr.2, addr.3, addr.4, addr.5]
    }
}

impl PartialEq<EtherAddr> for MacAddr {
    fn eq(&self, other: &EtherAddr) -> bool {
        *self == MacAddr::from(*other)
    }
}

impl fmt::Display for MacAddr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(
            fmt,
            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
            self.0, self.1, self.2, self.3, self.4, self.5
        )
    }
}

#[cfg(feature = "serde")]
impl Serialize for MacAddr {
    /// Serializes the MAC address.
    ///
    /// It serializes either to a string or its binary representation, depending on what the format
    /// prefers.
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        if serializer.is_human_readable() {
            serializer.serialize_str(&format!("{}", self))
        } else {
            serializer.serialize_bytes(&[self.0, self.1, self.2, self.3, self.4, self.5])
        }
    }
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for MacAddr {
    /// Deserializes the MAC address.
    ///
    /// It deserializes it from either a byte array (of size 6) or a string. If the format is
    /// self-descriptive (like JSON or MessagePack), it auto-detects it. If not, it obeys the
    /// human-readable property of the deserializer.
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        struct MacAddrVisitor;
        impl<'de> de::Visitor<'de> for MacAddrVisitor {
            type Value = MacAddr;

            fn visit_str<E: de::Error>(self, value: &str) -> Result<MacAddr, E> {
                value.parse().map_err(|err| E::custom(&format!("{}", err)))
            }

            fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<MacAddr, E> {
                if v.len() == 6 {
                    Ok(MacAddr::new(v[0], v[1], v[2], v[3], v[4], v[5]))
                } else {
                    Err(E::invalid_length(v.len(), &self))
                }
            }

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(
                    formatter,
                    "either a string representation of a MAC address or 6-element byte array"
                )
            }
        }

        // Decide what hint to provide to the deserializer based on if it is human readable or not
        if deserializer.is_human_readable() {
            deserializer.deserialize_str(MacAddrVisitor)
        } else {
            deserializer.deserialize_bytes(MacAddrVisitor)
        }
    }
}

impl fmt::Debug for MacAddr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, fmt)
    }
}

/// Represents an error which occurred whilst parsing a MAC address.
#[derive(Copy, Debug, PartialEq, Eq, Clone)]
pub enum ParseMacAddrErr {
    /// The MAC address has too many components, eg. 00:11:22:33:44:55:66.
    TooManyComponents,
    /// The MAC address has too few components, eg. 00:11.
    TooFewComponents,
    /// One of the components contains an invalid value, eg. 00:GG:22:33:44:55.
    InvalidComponent,
}

impl Error for ParseMacAddrErr {}

impl ParseMacAddrErr {
    fn description(&self) -> &str {
        match *self {
            ParseMacAddrErr::TooManyComponents => "Too many components in a MAC address string",
            ParseMacAddrErr::TooFewComponents => "Too few components in a MAC address string",
            ParseMacAddrErr::InvalidComponent => "Invalid component in a MAC address string",
        }
    }
}

impl fmt::Display for ParseMacAddrErr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl FromStr for MacAddr {
    type Err = ParseMacAddrErr;
    fn from_str(s: &str) -> Result<MacAddr, ParseMacAddrErr> {
        let mut parts = [0u8; 6];
        let splits = s.split(':');
        let mut i = 0;
        for split in splits {
            if i == 6 {
                return Err(ParseMacAddrErr::TooManyComponents);
            }
            match u8::from_str_radix(split, 16) {
                Ok(b) if split.len() != 0 => parts[i] = b,
                _ => return Err(ParseMacAddrErr::InvalidComponent),
            }
            i += 1;
        }

        if i == 6 {
            Ok(MacAddr(
                parts[0], parts[1], parts[2], parts[3], parts[4], parts[5],
            ))
        } else {
            Err(ParseMacAddrErr::TooFewComponents)
        }
    }
}

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

    #[test]
    fn mac_addr_from_str() {
        assert_eq!("00:00:00:00:00:00".parse(), Ok(MacAddr::zero()));
        assert_eq!("ff:ff:ff:ff:ff:ff".parse(), Ok(MacAddr::broadcast()));
        assert_eq!(
            "12:34:56:78:90:ab".parse(),
            Ok(MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB))
        );
        assert_eq!(
            "::::::".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "0::::::".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "::::0::".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "12:34:56:78".parse::<MacAddr>(),
            Err(ParseMacAddrErr::TooFewComponents)
        );
        assert_eq!(
            "12:34:56:78:".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "12:34:56:78:90".parse::<MacAddr>(),
            Err(ParseMacAddrErr::TooFewComponents)
        );
        assert_eq!(
            "12:34:56:78:90:".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
        assert_eq!(
            "12:34:56:78:90:00:00".parse::<MacAddr>(),
            Err(ParseMacAddrErr::TooManyComponents)
        );
        assert_eq!(
            "xx:xx:xx:xx:xx:xx".parse::<MacAddr>(),
            Err(ParseMacAddrErr::InvalidComponent)
        );
    }

    #[test]
    fn str_from_mac_addr() {
        assert_eq!(format!("{}", MacAddr::zero()), "00:00:00:00:00:00");
        assert_eq!(format!("{}", MacAddr::broadcast()), "ff:ff:ff:ff:ff:ff");
        assert_eq!(
            format!("{}", MacAddr(0x12, 0x34, 0x56, 0x78, 0x09, 0xAB)),
            "12:34:56:78:09:ab"
        );
    }

    #[test]
    fn type_of_addr() {
        assert!(MacAddr::zero().is_zero());
        assert!(MacAddr::broadcast().is_broadcast());

        let mac = MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB);
        assert!(mac.is_local());
        assert!(mac.is_unicast());

        let mac = MacAddr(0xac, 0x87, 0xa3, 0x07, 0x32, 0xb8);
        assert!(mac.is_universal());
        assert!(mac.is_unicast());
    }

    #[test]
    fn convertion() {
        let mac = MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB);
        let addr = [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB];

        assert_eq!(mac, MacAddr::from(addr));
        assert_eq!(addr, EtherAddr::from(mac));
        assert!(mac == addr);
    }

    #[cfg(feature = "serde")]
    mod serde {
        extern crate serde_test;
        use self::serde_test::{
            assert_de_tokens, assert_de_tokens_error, assert_tokens, Compact, Configure, Readable,
            Token,
        };
        use super::*;

        #[test]
        fn string() {
            let mac = MacAddr::new(0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
            assert_tokens(&mac.readable(), &[Token::Str("11:22:33:44:55:66")]);
            assert_de_tokens(&mac.readable(), &[Token::String("11:22:33:44:55:66")]);
            assert_de_tokens(&mac.readable(), &[Token::BorrowedStr("11:22:33:44:55:66")]);
            assert_de_tokens_error::<Readable<MacAddr>>(
                &[Token::Str("not an address")],
                "Invalid component in a MAC address string",
            );
            // It still can detect bytes if provided
            assert_de_tokens(
                &mac.readable(),
                &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
            );
        }

        #[test]
        fn bytes() {
            let mac = MacAddr::new(0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
            assert_tokens(
                &mac.compact(),
                &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
            );
            assert_de_tokens(
                &mac.compact(),
                &[Token::BorrowedBytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
            );
            let err = "invalid length 2, expected either a string representation of a MAC address or 6-element byte array";
            assert_de_tokens_error::<Compact<MacAddr>>(&[Token::Bytes(&[0x11, 0x33])], err);
            let err = "invalid length 7, expected either a string representation of a MAC address or 6-element byte array";
            assert_de_tokens_error::<Compact<MacAddr>>(
                &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77])],
                err,
            );
            // Still can decode string in the compact mode
            assert_de_tokens(&mac.compact(), &[Token::Str("11:22:33:44:55:66")]);
        }
    }
}
<|endoftext|>


<commit_before>use std::io::File;
use std::io::BufferedReader;

use racer;
use racer::util;
use racer::codecleaner;
use racer::codeiter;
use racer::typeinf;
use racer::ast;

pub fn find_closing_paren(src:&str, mut pos:usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0] as u8;
    let closeparen: u8 = ")".as_bytes()[0] as u8;
    let src_bytes = src.as_bytes();

    let mut levels = 0i32;
    loop {
        if src_bytes[pos] == closeparen {
            if levels == 0 {
                break;
            } else {
                levels -= 1;
            }
        }
        if src_bytes[pos] == openparen {
            levels += 1;
        }
        pos += 1;
    }
    return pos;
}

pub fn scope_start(src:&str, point:usize) -> usize {
    let masked_src = mask_comments(src);
    let s = &masked_src[..point];
    let mut pt = point;
    let mut levels = 0i32;
    for c in s.chars().rev() {
        if c == '{' {
            if levels == 0 {
                break;
            } else {
                levels -= 1;
            }
        }
        if c == '}' {
            levels += 1;
        }
        pt -= 1;
    }
    return pt;
}

pub fn find_stmt_start(msrc: &str, point: usize) -> Option<usize> {
    // iterate the scope to find the start of the statement
    let scopestart = scope_start(msrc, point);
    for (start, end) in codeiter::iter_stmts(&msrc[scopestart..]) {
        if (scopestart + end) > point {
            return Some(scopestart+start);
        }
    }
    return None;
}

pub fn get_local_module_path(msrc: &str, point: usize) -> Vec<String> {
    let mut v = Vec::new();
    get_local_module_path_(msrc, point, &mut v);
    return v;
}

fn get_local_module_path_(msrc: &str, point: usize, out: &mut Vec<String>) {
    for (start, end) in codeiter::iter_stmts(msrc) {
        if start < point && end > point {
            let blob = &msrc[start..end];
            if blob.starts_with("pub mod "){
                let p = typeinf::generate_skeleton_for_parsing(blob);
                ast::parse_mod(p).name.map(|name|{

                    let newstart = blob.find_str("{").unwrap() + 1;
                    out.push(name);
                    get_local_module_path_(&blob[newstart..],
                                       point - start - newstart, out);
                });
            }
        }
    }
}

pub fn find_impl_start(msrc: &str, point: usize, scopestart: usize) -> Option<usize> {

    for (start, end) in codeiter::iter_stmts(&msrc[scopestart..]) {
        if (scopestart + end) > point {
            let blob = &msrc[(scopestart + start)..];
            // TODO:: the following is a bit weak at matching traits. make this better
            if blob.starts_with("impl") ||
                blob.starts_with("trait") || blob.starts_with("pub trait") {
                return Some(scopestart + start);
            } else {
                let newstart = blob.find_str("{").unwrap() + 1;
                return find_impl_start(msrc, point, scopestart+start+newstart);
            }
        }
    }
    return None;
}

#[test]
fn finds_subnested_module() {
    let src = "
    pub mod foo {
        pub mod bar {
            here
        }
    }";
    let point = coords_to_point(src, 4, 12);
    let v = get_local_module_path(src, point);
    assert_eq!("foo", &v[0][]);
    assert_eq!("bar", &v[1][]);

    let point = coords_to_point(src, 2, 8);
    let v = get_local_module_path(src, point);
    assert_eq!("foo", &v[0][]);
}

pub fn split_into_context_and_completion<'a>(s: &'a str) -> (&'a str, &'a str, racer::CompletionType) {

    let mut start = 0;
    let s_bytes = s.as_bytes();
    let colon: u8 = ":".as_bytes()[0];
    let dot: u8 = ".".as_bytes()[0];

    for (i, c) in s.char_indices().rev() {
        if ! util::is_ident_char(c) {
            start = i+1;
            break;
        }
    }

    if start != 0 && s_bytes[start-1] == dot {    // field completion
        return (&s[..(start-1)], &s[start..], racer::CompletionType::CompleteField);
    }

    if start > 0 && s_bytes[start-1] == colon {  // path completion
        return (&s[..(start-2)], &s[start..], racer::CompletionType::CompletePath);
    }

    (&s[..start], &s[start..], racer::CompletionType::CompletePath)
}

pub fn get_start_of_search_expr(msrc: &str, point: usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0];
    let closeparen: u8 = ")".as_bytes()[0];
    let msrc_bytes = msrc.as_bytes();
    let mut levels = 0i32;
    let mut i = point-1;
    loop {
        if i == -1 {
            i = 0;
            break;
        }

        if msrc_bytes[i] == closeparen {
            levels += 1;
        }
        if levels == 0 && (!util::is_search_expr_char(msrc.char_at(i)) ||
                           util::is_double_dot(msrc,i)) {
            i += 1;
            break;
        }
        if msrc_bytes[i] == openparen && levels > 0 {
            levels -= 1;
        }

        i -= 1;
    }
    return i;
}

pub fn get_start_of_pattern(msrc: &str, point: usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0];
    let closeparen: u8 = ")".as_bytes()[0];
    let msrc_bytes = msrc.as_bytes();
    let mut levels = 0i32;
    let mut i = point-1;
    loop {
        if i == -1 {
            i = 0;
            break;
        }

        if msrc_bytes[i] == closeparen {
            levels += 1;
        }
        if levels == 0 && !util::is_pattern_char(msrc.char_at(i)) {
            i += 1;
            break;
        }
        if msrc_bytes[i] == openparen && levels > 0 {
            levels -= 1;
        }

        i -= 1;
    }
    return i;
}

#[test]
fn get_start_of_pattern_handles_variant() {
    assert_eq!(4, get_start_of_pattern("foo, Some(a) =>",13));
}

#[test]
fn get_start_of_pattern_handles_variant2() {
    assert_eq!(4, get_start_of_pattern("bla, ast::PatTup(ref tuple_elements) => {",36));
}

pub fn expand_search_expr(msrc: &str, point: usize) -> (usize,usize) {
    let start = get_start_of_search_expr(msrc, point);
    return (start, util::find_ident_end(msrc, point));
}

#[test]
fn expand_search_expr_finds_ident() {
    assert_eq!((0, 7), expand_search_expr("foo.bar", 5))
}

#[test]
fn expand_search_expr_handles_chained_calls() {
    assert_eq!((0, 20), expand_search_expr("yeah::blah.foo().bar", 18))
}

#[test]
fn expand_search_expr_handles_inline_closures() {
    assert_eq!((0, 24), expand_search_expr("yeah::blah.foo(||{}).bar", 22))
}
#[test]
fn expand_search_expr_handles_a_function_arg() {
    assert_eq!((5, 25), expand_search_expr("myfn(foo::new().baz().com)", 23))
}

#[test]
fn expand_search_expr_handles_pos_at_end_of_search_str() {
    assert_eq!((0, 7), expand_search_expr("foo.bar", 7))
}

pub fn mask_comments(src: &str) -> String {
    let mut result = String::new();
    let space = " ";

    let mut prev: usize = 0;
    for (start, end) in codecleaner::code_chunks(src) {
        for _ in ::std::iter::range(prev, start) {
            result.push_str(space);
        }
        result.push_str(&src[start..end]);
        prev = end;
    }
    return result;
}

pub fn mask_sub_scopes(src:&str) -> String {
    let mut result = String::new();
    let mut levels = 0i32;

    for c in src.chars() {
        if c == '}' {
            levels -= 1;
        }

        if c == '\n' {
            result.push(c);
        } else if levels > 0 {
            result.push(' ');
        } else {
            result.push(c);
        }

        if c == '{' {
            levels += 1;
        }
    }
    return result;
}

pub fn end_of_next_scope<'a>(src: &'a str) -> &'a str {
    let mut level = 0i32;
    let mut end = 0;
    for (i,c) in src.char_indices() {
        if c == '}' {
            level -= 1;
            if level == 0 {
                end = i + 1;
                break;
            }
        } else if c == '{' {
            level += 1;
        }
    }
    &src[..end]
}

pub fn coords_to_point(src: &str, mut linenum: usize, col: usize) -> usize {
    let mut point=0;
    for line in src.lines() {
        linenum -= 1;
        if linenum == 0 { break }
        point+=line.len() + 1;  // +1 for the \n
    }
    return point + col;
}

pub fn point_to_coords(src:&str, point:usize) -> (usize, usize) {
    let mut i = 0;
    let mut linestart = 0;
    let mut nlines = 1;  // lines start at 1
    while i != point {
        if src.char_at(i) == '\n' {
            nlines += 1;
            linestart = i+1;
        }
        i+=1;
    }
    return (nlines, point - linestart);
}

pub fn point_to_coords_from_file(path: &Path, point:usize) -> Option<(usize, usize)> {
    let mut lineno = 0;
    let mut file = BufferedReader::new(File::open(path));
    let mut p = 0;
    for line_r in file.lines() {
        let line = line_r.unwrap();
        lineno += 1;
        if point < (p + line.len()) {
            return Some((lineno, point - p));
        }
        p += line.len();
    }
    return None;
}

#[test]
fn coords_to_point_works() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}";
    assert!(coords_to_point(src, 3, 5) == 18);
}

#[test]
fn test_scope_start() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}
";
    let point = coords_to_point(src, 4, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn test_scope_start_handles_sub_scopes() {
    let src = "
fn myfn() {
    let a = 3;
    {
      let b = 4;
    }
    print(a);
}
";
    let point = coords_to_point(src, 7, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn masks_out_comments() {
    let src = "
this is some code
this is a line // with a comment
some more
";
    let r = mask_comments(src);

    assert!(src.len() == r.len());
    // characters at the start are the same
    assert!(src.as_bytes()[5] == r.as_bytes()[5]);
    // characters in the comments are masked
    let commentoffset = coords_to_point(src,3,23);
    assert!(&r[].char_at(commentoffset) == ' ');
    assert!(src.as_bytes()[commentoffset] != r.as_bytes()[commentoffset]);
    // characters afterwards are the same
    assert!(src.as_bytes()[src.len()-3] == r.as_bytes()[src.len()-3]);
}

#[test]
fn test_point_to_coords() {
    let src = "
fn myfn(b:usize) {
   let a = 3;
   if b == 12 {
       let a = 24;
       do_something_with(a);
   }
   do_something_with(a);
}
";
    round_trip_point_and_coords(src, 4, 5);
}

pub fn round_trip_point_and_coords(src:&str, lineno:usize, charno:usize) {
    let (a,b) = point_to_coords(src, coords_to_point(src, lineno, charno));
     assert_eq!((a,b),(lineno,charno));
}

#[test]
fn finds_end_of_struct_scope() {
    let src="
struct foo {
   a: usize,
   blah: ~str
}
Some other junk";

    let expected="
struct foo {
   a: usize,
   blah: ~str
}";
    let s = end_of_next_scope(src);
    assert_eq!(expected, s);
}

<commit_msg>Fix missing brackets<commit_after>use std::io::File;
use std::io::BufferedReader;

use racer;
use racer::util;
use racer::codecleaner;
use racer::codeiter;
use racer::typeinf;
use racer::ast;

pub fn find_closing_paren(src:&str, mut pos:usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0] as u8;
    let closeparen: u8 = ")".as_bytes()[0] as u8;
    let src_bytes = src.as_bytes();

    let mut levels = 0i32;
    loop {
        if src_bytes[pos] == closeparen {
            if levels == 0 {
                break;
            } else {
                levels -= 1;
            }
        }
        if src_bytes[pos] == openparen {
            levels += 1;
        }
        pos += 1;
    }
    return pos;
}

pub fn scope_start(src:&str, point:usize) -> usize {
    let masked_src = mask_comments(src);
    let s = &masked_src[..point];
    let mut pt = point;
    let mut levels = 0i32;
    for c in s.chars().rev() {
        if c == '{' {
            if levels == 0 {
                break;
            } else {
                levels -= 1;
            }
        }
        if c == '}' {
            levels += 1;
        }
        pt -= 1;
    }
    return pt;
}

pub fn find_stmt_start(msrc: &str, point: usize) -> Option<usize> {
    // iterate the scope to find the start of the statement
    let scopestart = scope_start(msrc, point);
    for (start, end) in codeiter::iter_stmts(&msrc[scopestart..]) {
        if (scopestart + end) > point {
            return Some(scopestart+start);
        }
    }
    return None;
}

pub fn get_local_module_path(msrc: &str, point: usize) -> Vec<String> {
    let mut v = Vec::new();
    get_local_module_path_(msrc, point, &mut v);
    return v;
}

fn get_local_module_path_(msrc: &str, point: usize, out: &mut Vec<String>) {
    for (start, end) in codeiter::iter_stmts(msrc) {
        if start < point && end > point {
            let blob = &msrc[start..end];
            if blob.starts_with("pub mod "){
                let p = typeinf::generate_skeleton_for_parsing(blob);
                ast::parse_mod(p).name.map(|name|{

                    let newstart = blob.find_str("{").unwrap() + 1;
                    out.push(name);
                    get_local_module_path_(&blob[newstart..],
                                       point - start - newstart, out);
                });
            }
        }
    }
}

pub fn find_impl_start(msrc: &str, point: usize, scopestart: usize) -> Option<usize> {

    for (start, end) in codeiter::iter_stmts(&msrc[scopestart..]) {
        if (scopestart + end) > point {
            let blob = &msrc[(scopestart + start)..];
            // TODO:: the following is a bit weak at matching traits. make this better
            if blob.starts_with("impl") ||
                blob.starts_with("trait") || blob.starts_with("pub trait") {
                return Some(scopestart + start);
            } else {
                let newstart = blob.find_str("{").unwrap() + 1;
                return find_impl_start(msrc, point, scopestart+start+newstart);
            }
        }
    }
    return None;
}

#[test]
fn finds_subnested_module() {
    let src = "
    pub mod foo {
        pub mod bar {
            here
        }
    }";
    let point = coords_to_point(src, 4, 12);
    let v = get_local_module_path(src, point);
    assert_eq!("foo", &v[0][]);
    assert_eq!("bar", &v[1][]);

    let point = coords_to_point(src, 2, 8);
    let v = get_local_module_path(src, point);
    assert_eq!("foo", &v[0][]);
}

pub fn split_into_context_and_completion<'a>(s: &'a str) -> (&'a str, &'a str, racer::CompletionType) {

    let mut start = 0;
    let s_bytes = s.as_bytes();
    let colon: u8 = ":".as_bytes()[0];
    let dot: u8 = ".".as_bytes()[0];

    for (i, c) in s.char_indices().rev() {
        if ! util::is_ident_char(c) {
            start = i+1;
            break;
        }
    }

    if start != 0 && s_bytes[start-1] == dot {    // field completion
        return (&s[..(start-1)], &s[start..], racer::CompletionType::CompleteField);
    }

    if start > 0 && s_bytes[start-1] == colon {  // path completion
        return (&s[..(start-2)], &s[start..], racer::CompletionType::CompletePath);
    }

    (&s[..start], &s[start..], racer::CompletionType::CompletePath)
}

pub fn get_start_of_search_expr(msrc: &str, point: usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0];
    let closeparen: u8 = ")".as_bytes()[0];
    let msrc_bytes = msrc.as_bytes();
    let mut levels = 0i32;
    let mut i = point-1;
    loop {
        if i == -1 {
            i = 0;
            break;
        }

        if msrc_bytes[i] == closeparen {
            levels += 1;
        }
        if levels == 0 && (!util::is_search_expr_char(msrc.char_at(i)) ||
                           util::is_double_dot(msrc,i)) {
            i += 1;
            break;
        }
        if msrc_bytes[i] == openparen && levels > 0 {
            levels -= 1;
        }

        i -= 1;
    }
    return i;
}

pub fn get_start_of_pattern(msrc: &str, point: usize) -> usize {
    let openparen: u8 = "(".as_bytes()[0];
    let closeparen: u8 = ")".as_bytes()[0];
    let msrc_bytes = msrc.as_bytes();
    let mut levels = 0i32;
    let mut i = point-1;
    loop {
        if i == -1 {
            i = 0;
            break;
        }

        if msrc_bytes[i] == closeparen {
            levels += 1;
        }
        if levels == 0 && !util::is_pattern_char(msrc.char_at(i)) {
            i += 1;
            break;
        }
        if msrc_bytes[i] == openparen && levels > 0 {
            levels -= 1;
        }

        i -= 1;
    }
    return i;
}

#[test]
fn get_start_of_pattern_handles_variant() {
    assert_eq!(4, get_start_of_pattern("foo, Some(a) =>",13));
}

#[test]
fn get_start_of_pattern_handles_variant2() {
    assert_eq!(4, get_start_of_pattern("bla, ast::PatTup(ref tuple_elements) => {",36));
}

pub fn expand_search_expr(msrc: &str, point: usize) -> (usize,usize) {
    let start = get_start_of_search_expr(msrc, point);
    return (start, util::find_ident_end(msrc, point));
}

#[test]
fn expand_search_expr_finds_ident() {
    assert_eq!((0, 7), expand_search_expr("foo.bar", 5))
}

#[test]
fn expand_search_expr_handles_chained_calls() {
    assert_eq!((0, 20), expand_search_expr("yeah::blah.foo().bar", 18))
}

#[test]
fn expand_search_expr_handles_inline_closures() {
    assert_eq!((0, 24), expand_search_expr("yeah::blah.foo(||{}).bar", 22))
}
#[test]
fn expand_search_expr_handles_a_function_arg() {
    assert_eq!((5, 25), expand_search_expr("myfn(foo::new().baz().com)", 23))
}

#[test]
fn expand_search_expr_handles_pos_at_end_of_search_str() {
    assert_eq!((0, 7), expand_search_expr("foo.bar", 7))
}

pub fn mask_comments(src: &str) -> String {
    let mut result = String::new();
    let space = " ";

    let mut prev: usize = 0;
    for (start, end) in codecleaner::code_chunks(src) {
        for _ in ::std::iter::range(prev, start) {
            result.push_str(space);
        }
        result.push_str(&src[start..end]);
        prev = end;
    }
    return result;
}

pub fn mask_sub_scopes(src:&str) -> String {
    let mut result = String::new();
    let mut levels = 0i32;

    for c in src.chars() {
        if c == '}' {
            levels -= 1;
        }

        if c == '\n' {
            result.push(c);
        } else if levels > 0 {
            result.push(' ');
        } else {
            result.push(c);
        }

        if c == '{' {
            levels += 1;
        }
    }
    return result;
}

pub fn end_of_next_scope<'a>(src: &'a str) -> &'a str {
    let mut level = 0i32;
    let mut end = 0;
    for (i,c) in src.char_indices() {
        if c == '}' {
            level -= 1;
            if level == 0 {
                end = i + 1;
                break;
            }
        } else if c == '{' {
            level += 1;
        }
    }
    &src[..end]
}

pub fn coords_to_point(src: &str, mut linenum: usize, col: usize) -> usize {
    let mut point=0;
    for line in src.lines() {
        linenum -= 1;
        if linenum == 0 { break }
        point+=line.len() + 1;  // +1 for the \n
    }
    return point + col;
}

pub fn point_to_coords(src:&str, point:usize) -> (usize, usize) {
    let mut i = 0;
    let mut linestart = 0;
    let mut nlines = 1;  // lines start at 1
    while i != point {
        if src.char_at(i) == '\n' {
            nlines += 1;
            linestart = i+1;
        }
        i+=1;
    }
    return (nlines, point - linestart);
}

pub fn point_to_coords_from_file(path: &Path, point:usize) -> Option<(usize, usize)> {
    let mut lineno = 0;
    let mut file = BufferedReader::new(File::open(path));
    let mut p = 0;
    for line_r in file.lines() {
        let line = line_r.unwrap();
        lineno += 1;
        if point < (p + line.len()) {
            return Some((lineno, point - p));
        }
        p += line.len();
    }
    return None;
}

#[test]
fn coords_to_point_works() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}";
    assert!(coords_to_point(src, 3, 5) == 18);
}

#[test]
fn test_scope_start() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}
";
    let point = coords_to_point(src, 4, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn test_scope_start_handles_sub_scopes() {
    let src = "
fn myfn() {
    let a = 3;
    {
      let b = 4;
    }
    print(a);
}
";
    let point = coords_to_point(src, 7, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn masks_out_comments() {
    let src = "
this is some code
this is a line // with a comment
some more
";
    let r = mask_comments(src);

    assert!(src.len() == r.len());
    // characters at the start are the same
    assert!(src.as_bytes()[5] == r.as_bytes()[5]);
    // characters in the comments are masked
    let commentoffset = coords_to_point(src,3,23);
    assert!((&r[]).char_at(commentoffset) == ' ');
    assert!(src.as_bytes()[commentoffset] != r.as_bytes()[commentoffset]);
    // characters afterwards are the same
    assert!(src.as_bytes()[src.len()-3] == r.as_bytes()[src.len()-3]);
}

#[test]
fn test_point_to_coords() {
    let src = "
fn myfn(b:usize) {
   let a = 3;
   if b == 12 {
       let a = 24;
       do_something_with(a);
   }
   do_something_with(a);
}
";
    round_trip_point_and_coords(src, 4, 5);
}

pub fn round_trip_point_and_coords(src:&str, lineno:usize, charno:usize) {
    let (a,b) = point_to_coords(src, coords_to_point(src, lineno, charno));
     assert_eq!((a,b),(lineno,charno));
}

#[test]
fn finds_end_of_struct_scope() {
    let src="
struct foo {
   a: usize,
   blah: ~str
}
Some other junk";

    let expected="
struct foo {
   a: usize,
   blah: ~str
}";
    let s = end_of_next_scope(src);
    assert_eq!(expected, s);
}

<|endoftext|>


<commit_before>// Test that we use fully-qualified type names in error messages.

// ignore-test

type T1 = usize;
type T2 = isize;

fn bar(x: T1) -> T2 {
    return x;
    //~^ ERROR mismatched types: expected `T2`, found `T1`
}

fn main() {
}
<commit_msg>Remove ignored type alias test<commit_after><|endoftext|>