<commit_before>use buffer::{Content, Buffer, BufferAny, BufferType, BufferMode, BufferCreationError};
use buffer::{BufferSlice, BufferMutSlice};
use uniforms::{AsUniformValue, UniformBlock, UniformValue, LayoutMismatchError};
use program;

use gl;
use GlObject;

use std::ops::{Deref, DerefMut};

use backend::Facade;

/// Buffer that contains a uniform block.
#[derive(Debug)]
pub struct UniformBuffer<T: ?Sized> where T: Content {
    buffer: Buffer<T>,
}

/// Same as `UniformBuffer` but doesn't contain any information about the type.
#[derive(Debug)]
pub struct TypelessUniformBuffer {
    buffer: BufferAny,
}

impl<T: ?Sized + Content> GlObject for UniformBuffer<T> {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

impl<T> UniformBuffer<T> where T: Copy {
    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn new<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                  where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Default)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn dynamic<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                      where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Dynamic)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn persistent<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                  where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Persistent)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn immutable<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                        where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Immutable)
    }

    #[inline]
    fn new_impl<F: ?Sized>(facade: &F, data: T, mode: BufferMode)
                   -> Result<UniformBuffer<T>, BufferCreationError>
                   where F: Facade
    {
        let buffer = try!(Buffer::new(facade, &data, BufferType::UniformBuffer, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError> where F: Facade {
        UniformBuffer::empty_impl(facade, BufferMode::Default)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_dynamic<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                            where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Dynamic)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_persistent<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                               where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Persistent)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_immutable<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                              where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Immutable)
    }

    #[inline]
    fn empty_impl<F: ?Sized>(facade: &F, mode: BufferMode) -> Result<UniformBuffer<T>, BufferCreationError>
                     where F: Facade
    {
        let buffer = try!(Buffer::empty(facade, BufferType::UniformBuffer, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }
}

impl<T: ?Sized> UniformBuffer<T> where T: Content {
    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized<F: ?Sized>(facade: &F, size: usize)
                            -> Result<UniformBuffer<T>, BufferCreationError>
                            where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Default)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_dynamic<F: ?Sized>(facade: &F, size: usize)
                                    -> Result<UniformBuffer<T>, BufferCreationError>
                                    where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Dynamic)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_persistent<F: ?Sized>(facade: &F, size: usize)
                                       -> Result<UniformBuffer<T>, BufferCreationError>
                                       where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Persistent)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_immutable<F: ?Sized>(facade: &F, size: usize)
                                      -> Result<UniformBuffer<T>, BufferCreationError>
                                      where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Immutable)
    }

    #[inline]
    fn empty_unsized_impl<F: ?Sized>(facade: &F, size: usize, mode: BufferMode)
                             -> Result<UniformBuffer<T>, BufferCreationError>
                             where F: Facade
    {
        let buffer = try!(Buffer::empty_unsized(facade, BufferType::UniformBuffer, size, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }
}

impl<T: ?Sized> Deref for UniformBuffer<T> where T: Content {
    type Target = Buffer<T>;

    #[inline]
    fn deref(&self) -> &Buffer<T> {
        &self.buffer
    }
}

impl<T: ?Sized> DerefMut for UniformBuffer<T> where T: Content {
    #[inline]
    fn deref_mut(&mut self) -> &mut Buffer<T> {
        &mut self.buffer
    }
}

impl<'a, T: ?Sized> From<&'a UniformBuffer<T>> for BufferSlice<'a, T> where T: Content {
    #[inline]
    fn from(b: &'a UniformBuffer<T>) -> BufferSlice<'a, T> {
        b.buffer.as_slice()
    }
}

impl<'a, T: ?Sized> From<&'a mut UniformBuffer<T>> for BufferMutSlice<'a, T> where T: Content {
    #[inline]
    fn from(b: &'a mut UniformBuffer<T>) -> BufferMutSlice<'a, T> {
        b.buffer.as_mut_slice()
    }
}

impl<'a, T: ?Sized> AsUniformValue for &'a UniformBuffer<T> where T: UniformBlock + Content {
    #[inline]
    fn as_uniform_value(&self) -> UniformValue {
        #[inline]
        fn f<T: ?Sized>(block: &program::UniformBlock)
                        -> Result<(), LayoutMismatchError> where T: UniformBlock + Content
        {
            // TODO: more checks?
            T::matches(&block.layout, 0)
        }

        UniformValue::Block(self.buffer.as_slice_any(), f::<T>)
    }
}
<commit_msg>Add usage example to UniformBuffer.<commit_after>use buffer::{Content, Buffer, BufferAny, BufferType, BufferMode, BufferCreationError};
use buffer::{BufferSlice, BufferMutSlice};
use uniforms::{AsUniformValue, UniformBlock, UniformValue, LayoutMismatchError};
use program;

use gl;
use GlObject;

use std::ops::{Deref, DerefMut};

use backend::Facade;

/// Buffer that contains a uniform block.
///
/// For example, to use a `UniformBuffer<[u32; 8]`, you must declare it as
///
///     uniform MyBlock {
///         uint array[8];
///     };
///
/// and pass it to `uniform!` like this:
///
///     uniform! {
///         MyBlock: &buffer,
///     }
#[derive(Debug)]
pub struct UniformBuffer<T: ?Sized> where T: Content {
    buffer: Buffer<T>,
}

/// Same as `UniformBuffer` but doesn't contain any information about the type.
#[derive(Debug)]
pub struct TypelessUniformBuffer {
    buffer: BufferAny,
}

impl<T: ?Sized + Content> GlObject for UniformBuffer<T> {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

impl<T> UniformBuffer<T> where T: Copy {
    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn new<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                  where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Default)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn dynamic<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                      where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Dynamic)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn persistent<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                  where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Persistent)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn immutable<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                        where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Immutable)
    }

    #[inline]
    fn new_impl<F: ?Sized>(facade: &F, data: T, mode: BufferMode)
                   -> Result<UniformBuffer<T>, BufferCreationError>
                   where F: Facade
    {
        let buffer = try!(Buffer::new(facade, &data, BufferType::UniformBuffer, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError> where F: Facade {
        UniformBuffer::empty_impl(facade, BufferMode::Default)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_dynamic<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                            where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Dynamic)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_persistent<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                               where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Persistent)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_immutable<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                              where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Immutable)
    }

    #[inline]
    fn empty_impl<F: ?Sized>(facade: &F, mode: BufferMode) -> Result<UniformBuffer<T>, BufferCreationError>
                     where F: Facade
    {
        let buffer = try!(Buffer::empty(facade, BufferType::UniformBuffer, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }
}

impl<T: ?Sized> UniformBuffer<T> where T: Content {
    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized<F: ?Sized>(facade: &F, size: usize)
                            -> Result<UniformBuffer<T>, BufferCreationError>
                            where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Default)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_dynamic<F: ?Sized>(facade: &F, size: usize)
                                    -> Result<UniformBuffer<T>, BufferCreationError>
                                    where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Dynamic)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_persistent<F: ?Sized>(facade: &F, size: usize)
                                       -> Result<UniformBuffer<T>, BufferCreationError>
                                       where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Persistent)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_immutable<F: ?Sized>(facade: &F, size: usize)
                                      -> Result<UniformBuffer<T>, BufferCreationError>
                                      where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Immutable)
    }

    #[inline]
    fn empty_unsized_impl<F: ?Sized>(facade: &F, size: usize, mode: BufferMode)
                             -> Result<UniformBuffer<T>, BufferCreationError>
                             where F: Facade
    {
        let buffer = try!(Buffer::empty_unsized(facade, BufferType::UniformBuffer, size, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }
}

impl<T: ?Sized> Deref for UniformBuffer<T> where T: Content {
    type Target = Buffer<T>;

    #[inline]
    fn deref(&self) -> &Buffer<T> {
        &self.buffer
    }
}

impl<T: ?Sized> DerefMut for UniformBuffer<T> where T: Content {
    #[inline]
    fn deref_mut(&mut self) -> &mut Buffer<T> {
        &mut self.buffer
    }
}

impl<'a, T: ?Sized> From<&'a UniformBuffer<T>> for BufferSlice<'a, T> where T: Content {
    #[inline]
    fn from(b: &'a UniformBuffer<T>) -> BufferSlice<'a, T> {
        b.buffer.as_slice()
    }
}

impl<'a, T: ?Sized> From<&'a mut UniformBuffer<T>> for BufferMutSlice<'a, T> where T: Content {
    #[inline]
    fn from(b: &'a mut UniformBuffer<T>) -> BufferMutSlice<'a, T> {
        b.buffer.as_mut_slice()
    }
}

impl<'a, T: ?Sized> AsUniformValue for &'a UniformBuffer<T> where T: UniformBlock + Content {
    #[inline]
    fn as_uniform_value(&self) -> UniformValue {
        #[inline]
        fn f<T: ?Sized>(block: &program::UniformBlock)
                        -> Result<(), LayoutMismatchError> where T: UniformBlock + Content
        {
            // TODO: more checks?
            T::matches(&block.layout, 0)
        }

        UniformValue::Block(self.buffer.as_slice_any(), f::<T>)
    }
}
<|endoftext|>


<commit_before>use super::Vector;
use super::Vector2;

pub struct Vector2f {
    pub x: f32,
    pub y: f32,
}

impl Default for Vector2f {
    fn default() -> Vector2f {
        Vector2f {
            x: 0f32,
            y: 0f32,
        }
    }
}

impl Vector<Vector2f, f32> for Vector2f {
    fn add(&mut self, v: &Vector2f) -> &mut Self {
        self.x += v.x;
        self.y += v.y;
        self
    }

    fn add_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x + v.x;
        dest.y = self.y + v.y;
    }

    fn angle(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn angle_cos(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn distance(&self, v: &Vector2f) -> f32 {
        self.distance_squared(v).sqrt()
    }

    fn distance_squared(&self, v: &Vector2f) -> f32 {
        let dx = self.x - v.x;
        let dy = self.y - v.y;
        (dx * dx) + (dy * dy)
    }

    fn dot(&self, v: &Vector2f) -> f32 {
        (self.x * v.x) + (self.y * v.y)
    }

    fn fma_scalar(&mut self, a: f32, b: &Vector2f) -> &mut Self {
        self.x += a * b.x;
        self.y += a * b.y;
        self
    }

    fn fma_scalar_into(&self, a: f32, b: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x + (a * b.x);
        dest.y = self.y + (a * b.y);
    }

    fn fma_vector(&mut self, a: &Vector2f, b: &Vector2f) -> &mut Self {
        self.x += a.x * b.x;
        self.y += a.y * b.y;
        self
    }

    fn fma_vector_into(&self, a: &Vector2f, b: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x + (a.x * b.x);
        dest.y = self.y + (a.y * b.y);
    }

    fn length(&self) -> f32 {
        self.length_squared().sqrt()
    }

    fn length_squared(&self) -> f32 {
        (self.x * self.x) + (self.y * self.y)
    }

    fn lerp(&mut self, other: &Vector2f, t: f32) -> &mut Self {
        unimplemented!()
    }

    fn lerp_into(&self, other: &Vector2f, t: f32, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn mul_scalar(&mut self, s: f32) -> &mut Self {
        self.x *= s;
        self.y *= s;
        self
    }

    fn mul_scalar_into(&self, s: f32, dest: &mut Vector2f) {
        dest.x = self.x * s;
        dest.y = self.y * s;
    }

    fn mul_vector(&mut self, v: &Vector2f) -> &mut Self {
        self.x *= v.x;
        self.y *= v.y;
        self
    }

    fn mul_vector_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x * v.x;
        dest.y = self.y * v.y;
    }

    fn negate(&mut self) -> &mut Self {
        self.x = -self.x;
        self.y = -self.y;
        self
    }

    fn negate_into(&self, dest: &mut Vector2f) {
        dest.x = -self.x;
        dest.y = -self.y;
    }

    fn normalize(&mut self) -> &mut Self {
        let inv_length = 1f32 / self.length();
        self.x *= inv_length;
        self.y *= inv_length;
        self
    }

    fn normalize_into(&self, dest: &mut Vector2f) {
        let inv_length = 1f32 / self.length();
        dest.x = self.x * inv_length;
        dest.y = self.y * inv_length;
    }

    fn set(&mut self, v: &Vector2f) -> &mut Self {
        self.x = v.x;
        self.y = v.y;
        self
    }

    fn sub(&mut self, v: &Vector2f) -> &mut Self {
        self.x -= v.x;
        self.y -= v.y;
        self
    }

    fn sub_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x - v.x;
        dest.y = self.y - v.y;
    }

    fn zero(&mut self) -> &mut Self {
        self.x = 0f32;
        self.y = 0f32;
        self
    }
}

impl Vector2<Vector2f, f32> for Vector2f {
    fn new(x: f32, y: f32) -> Self {
        Vector2f {
            x: x,
            y: y,
        }
    }

    fn add_components(&mut self, x: f32, y: f32) -> &mut Self {
        unimplemented!()
    }

    fn add_components_into(&self, x: f32, y: f32, dest: &mut Vector2f) {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::super::Vector;
    use super::super::Vector2;
    use super::Vector2f;

    use std;

    #[test]
    fn test_new() {
        let a = Vector2f::new(1f32, 2f32);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
    }

    #[test]
    fn test_add() {
        let mut a = Vector2f::default();
        let b = Vector2f::new(1f32, 2f32);

        a.add(&b);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
    }

    #[test]
    fn test_add_into() {
        let a = Vector2f::new(1f32, 1f32);
        let b = Vector2f::new(1f32, 2f32);
        let mut c = Vector2f::default();

        a.add_into(&b, &mut c);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 3f32);
    }

    #[test]
    fn test_distance() {
        let a = Vector2f::new(2f32, 1f32);
        let b = Vector2f::new(0f32, 1f32);

        let target_distance = 2f32;
        let distance = a.distance(&b);

        assert_eq!(target_distance, distance);
    }

    #[test]
    fn test_distance_squared() {
        let a = Vector2f::new(2f32, 1f32);
        let b = Vector2f::new(0f32, 1f32);

        let target_distance_sq = 4f32; //distance is 2
        let distance_sq = a.distance_squared(&b);

        assert_eq!(target_distance_sq, distance_sq);
    }

    #[test]
    fn test_dot() {
        let a = Vector2f::new(2f32, 1f32);
        let b = Vector2f::new(1f32, 1f32);

        let target_dot = 3f32;
        let dot = a.dot(&b);

        assert_eq!(target_dot, dot);
    }

    #[test]
    fn test_fma_scalar() {
        let mut a = Vector2f::new(1f32, 1f32);
        let b = 2f32;
        let c = Vector2f::new(2f32, 3f32);

        a.fma_scalar(b, &c);

        assert_eq!(a.x, 5f32);
        assert_eq!(a.y, 7f32);
    }

    #[test]
    fn test_fma_scalar_into() {
        let a = Vector2f::new(1f32, 1f32);
        let b = 2f32;
        let c = Vector2f::new(2f32, 3f32);
        let mut d = Vector2f::new(0f32, 0f32);

        a.fma_scalar_into(b, &c, &mut d);

        assert_eq!(d.x, 5f32);
        assert_eq!(d.y, 7f32);
    }

    #[test]
    fn test_fma_vector() {
        let mut a = Vector2f::new(1f32, 1f32);
        let b = Vector2f::new(2f32, 3f32);
        let c = Vector2f::new(2f32, 3f32);

        a.fma_vector(&b, &c);

        assert_eq!(a.x, 5f32);
        assert_eq!(a.y, 10f32);
    }

    #[test]
    fn test_fma_vector_into() {
        let a = Vector2f::new(1f32, 1f32);
        let b = Vector2f::new(2f32, 3f32);
        let c = Vector2f::new(2f32, 3f32);
        let mut d = Vector2f::new(0f32, 0f32);

        a.fma_vector_into(&b, &c, &mut d);

        assert_eq!(d.x, 5f32);
        assert_eq!(d.y, 10f32);
    }

    #[test]
    fn test_length() {
        let a = Vector2f::new(3f32, 4f32);

        let target_length = 5f32; //length should be 5 because of the 3:4:5 triangle
        let length = a.length();

        assert_eq!(target_length, length);
    }

    #[test]
    fn test_length_squared() {
        let a = Vector2f::new(3f32, 4f32);

        let target_length_sq = 25f32; //length should be 5 because of the 3:4:5 triangle
        let length_sq = a.length_squared();

        assert_eq!(target_length_sq, length_sq);
    }

    #[test]
    fn test_mul_scalar() {
        let mut a = Vector2f::new(1f32, 2f32);
        let b = 2f32;

        a.mul_scalar(b);

        assert_eq!(a.x, 2f32);
        assert_eq!(a.y, 4f32);
    }

    #[test]
    fn test_mul_scalar_into() {
        let a = Vector2f::new(1f32, 2f32);
        let b = 2f32;
        let mut c = Vector2::new(0f32, 0f32);

        a.mul_scalar_into(b, &mut c);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 4f32);
    }

    #[test]
    fn test_mul_vector() {
        let mut a = Vector2f::new(1f32, 2f32);
        let b = Vector2f::new(2f32, 3f32);

        a.mul_vector(&b);

        assert_eq!(a.x, 2f32);
        assert_eq!(a.y, 6f32);
    }

    #[test]
    fn test_mul_vector_into() {
        let a = Vector2f::new(1f32, 2f32);
        let b = Vector2f::new(2f32, 3f32);
        let mut c = Vector2::new(0f32, 0f32);

        a.mul_vector_into(&b, &mut c);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 6f32);
    }

    #[test]
    fn test_negate() {
        let mut a = Vector2f::new(1f32, 2f32);

        a.negate();

        assert_eq!(a.x, -1f32);
        assert_eq!(a.y, -2f32);
    }

    #[test]
    fn test_negate_into() {
        let a = Vector2f::new(1f32, 2f32);
        let mut b = Vector2f::new(0f32, 0f32);

        a.negate_into(&mut b);

        assert_eq!(b.x, -1f32);
        assert_eq!(b.y, -2f32);
    }

    #[test]
    fn test_normalize() {
        let mut a = Vector2f::new(1f32, 2f32);

        a.normalize();

        assert!((1f32 - a.length()).abs() < std::f32::EPSILON);
    }

    #[test]
    fn test_normalize_into() {
        let a = Vector2f::new(1f32, 2f32);
        let mut b = Vector2f::new(0f32, 0f32);

        a.normalize_into(&mut b);

        assert!((1f32 - b.length()).abs() < std::f32::EPSILON);
    }

    #[test]
    fn test_set() {
        let mut a = Vector2f::new(0f32, 0f32);
        let b = Vector2f::new(1f32, 2f32);

        a.set(&b);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
    }

    #[test]
    fn test_sub() {
        let mut a = Vector2f::new(2f32, 5f32);
        let b = Vector2f::new(1f32, 2f32);

        a.sub(&b);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 3f32);
    }

    #[test]
    fn test_sub_into() {
        let a = Vector2f::new(2f32, 5f32);
        let b = Vector2f::new(1f32, 2f32);
        let mut c = Vector2f::new(0f32, 0f32);

        a.sub_into(&b, &mut c);

        assert_eq!(c.x, 1f32);
        assert_eq!(c.y, 3f32);
    }

    #[test]
    fn test_zero() {
        let mut a = Vector2f::new(1f32, 2f32);

        a.zero();

        assert_eq!(a.x, 0f32);
        assert_eq!(a.y, 0f32);
    }
}
<commit_msg>switch to built-in mul_add function for fma impls<commit_after>use super::Vector;
use super::Vector2;

pub struct Vector2f {
    pub x: f32,
    pub y: f32,
}

impl Default for Vector2f {
    fn default() -> Vector2f {
        Vector2f {
            x: 0f32,
            y: 0f32,
        }
    }
}

impl Vector<Vector2f, f32> for Vector2f {
    fn add(&mut self, v: &Vector2f) -> &mut Self {
        self.x += v.x;
        self.y += v.y;
        self
    }

    fn add_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x + v.x;
        dest.y = self.y + v.y;
    }

    fn angle(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn angle_cos(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn distance(&self, v: &Vector2f) -> f32 {
        self.distance_squared(v).sqrt()
    }

    fn distance_squared(&self, v: &Vector2f) -> f32 {
        let dx = self.x - v.x;
        let dy = self.y - v.y;
        (dx * dx) + (dy * dy)
    }

    fn dot(&self, v: &Vector2f) -> f32 {
        (self.x * v.x) + (self.y * v.y)
    }

    fn fma_scalar(&mut self, a: f32, b: &Vector2f) -> &mut Self {
        self.x = a.mul_add(b.x, self.x);
        self.y = a.mul_add(b.y, self.y);
        self
    }

    fn fma_scalar_into(&self, a: f32, b: &Vector2f, dest: &mut Vector2f) {
        dest.x = a.mul_add(b.x, self.x);
        dest.y = a.mul_add(b.y, self.y);
    }

    fn fma_vector(&mut self, a: &Vector2f, b: &Vector2f) -> &mut Self {
        self.x = a.x.mul_add(b.x, self.x);
        self.y = a.y.mul_add(b.y, self.y);
        self
    }

    fn fma_vector_into(&self, a: &Vector2f, b: &Vector2f, dest: &mut Vector2f) {
        dest.x = a.x.mul_add(b.x, self.x);
        dest.y = a.y.mul_add(b.y, self.y);
    }

    fn length(&self) -> f32 {
        self.length_squared().sqrt()
    }

    fn length_squared(&self) -> f32 {
        (self.x * self.x) + (self.y * self.y)
    }

    fn lerp(&mut self, other: &Vector2f, t: f32) -> &mut Self {
        unimplemented!()
    }

    fn lerp_into(&self, other: &Vector2f, t: f32, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn mul_scalar(&mut self, s: f32) -> &mut Self {
        self.x *= s;
        self.y *= s;
        self
    }

    fn mul_scalar_into(&self, s: f32, dest: &mut Vector2f) {
        dest.x = self.x * s;
        dest.y = self.y * s;
    }

    fn mul_vector(&mut self, v: &Vector2f) -> &mut Self {
        self.x *= v.x;
        self.y *= v.y;
        self
    }

    fn mul_vector_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x * v.x;
        dest.y = self.y * v.y;
    }

    fn negate(&mut self) -> &mut Self {
        self.x = -self.x;
        self.y = -self.y;
        self
    }

    fn negate_into(&self, dest: &mut Vector2f) {
        dest.x = -self.x;
        dest.y = -self.y;
    }

    fn normalize(&mut self) -> &mut Self {
        let inv_length = 1f32 / self.length();
        self.x *= inv_length;
        self.y *= inv_length;
        self
    }

    fn normalize_into(&self, dest: &mut Vector2f) {
        let inv_length = 1f32 / self.length();
        dest.x = self.x * inv_length;
        dest.y = self.y * inv_length;
    }

    fn set(&mut self, v: &Vector2f) -> &mut Self {
        self.x = v.x;
        self.y = v.y;
        self
    }

    fn sub(&mut self, v: &Vector2f) -> &mut Self {
        self.x -= v.x;
        self.y -= v.y;
        self
    }

    fn sub_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x - v.x;
        dest.y = self.y - v.y;
    }

    fn zero(&mut self) -> &mut Self {
        self.x = 0f32;
        self.y = 0f32;
        self
    }
}

impl Vector2<Vector2f, f32> for Vector2f {
    fn new(x: f32, y: f32) -> Self {
        Vector2f {
            x: x,
            y: y,
        }
    }

    fn add_components(&mut self, x: f32, y: f32) -> &mut Self {
        unimplemented!()
    }

    fn add_components_into(&self, x: f32, y: f32, dest: &mut Vector2f) {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::super::Vector;
    use super::super::Vector2;
    use super::Vector2f;

    use std;

    #[test]
    fn test_new() {
        let a = Vector2f::new(1f32, 2f32);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
    }

    #[test]
    fn test_add() {
        let mut a = Vector2f::default();
        let b = Vector2f::new(1f32, 2f32);

        a.add(&b);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
    }

    #[test]
    fn test_add_into() {
        let a = Vector2f::new(1f32, 1f32);
        let b = Vector2f::new(1f32, 2f32);
        let mut c = Vector2f::default();

        a.add_into(&b, &mut c);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 3f32);
    }

    #[test]
    fn test_distance() {
        let a = Vector2f::new(2f32, 1f32);
        let b = Vector2f::new(0f32, 1f32);

        let target_distance = 2f32;
        let distance = a.distance(&b);

        assert_eq!(target_distance, distance);
    }

    #[test]
    fn test_distance_squared() {
        let a = Vector2f::new(2f32, 1f32);
        let b = Vector2f::new(0f32, 1f32);

        let target_distance_sq = 4f32; //distance is 2
        let distance_sq = a.distance_squared(&b);

        assert_eq!(target_distance_sq, distance_sq);
    }

    #[test]
    fn test_dot() {
        let a = Vector2f::new(2f32, 1f32);
        let b = Vector2f::new(1f32, 1f32);

        let target_dot = 3f32;
        let dot = a.dot(&b);

        assert_eq!(target_dot, dot);
    }

    #[test]
    fn test_fma_scalar() {
        let mut a = Vector2f::new(1f32, 1f32);
        let b = 2f32;
        let c = Vector2f::new(2f32, 3f32);

        a.fma_scalar(b, &c);

        assert_eq!(a.x, 5f32);
        assert_eq!(a.y, 7f32);
    }

    #[test]
    fn test_fma_scalar_into() {
        let a = Vector2f::new(1f32, 1f32);
        let b = 2f32;
        let c = Vector2f::new(2f32, 3f32);
        let mut d = Vector2f::new(0f32, 0f32);

        a.fma_scalar_into(b, &c, &mut d);

        assert_eq!(d.x, 5f32);
        assert_eq!(d.y, 7f32);
    }

    #[test]
    fn test_fma_vector() {
        let mut a = Vector2f::new(1f32, 1f32);
        let b = Vector2f::new(2f32, 3f32);
        let c = Vector2f::new(2f32, 3f32);

        a.fma_vector(&b, &c);

        assert_eq!(a.x, 5f32);
        assert_eq!(a.y, 10f32);
    }

    #[test]
    fn test_fma_vector_into() {
        let a = Vector2f::new(1f32, 1f32);
        let b = Vector2f::new(2f32, 3f32);
        let c = Vector2f::new(2f32, 3f32);
        let mut d = Vector2f::new(0f32, 0f32);

        a.fma_vector_into(&b, &c, &mut d);

        assert_eq!(d.x, 5f32);
        assert_eq!(d.y, 10f32);
    }

    #[test]
    fn test_length() {
        let a = Vector2f::new(3f32, 4f32);

        let target_length = 5f32; //length should be 5 because of the 3:4:5 triangle
        let length = a.length();

        assert_eq!(target_length, length);
    }

    #[test]
    fn test_length_squared() {
        let a = Vector2f::new(3f32, 4f32);

        let target_length_sq = 25f32; //length should be 5 because of the 3:4:5 triangle
        let length_sq = a.length_squared();

        assert_eq!(target_length_sq, length_sq);
    }

    #[test]
    fn test_mul_scalar() {
        let mut a = Vector2f::new(1f32, 2f32);
        let b = 2f32;

        a.mul_scalar(b);

        assert_eq!(a.x, 2f32);
        assert_eq!(a.y, 4f32);
    }

    #[test]
    fn test_mul_scalar_into() {
        let a = Vector2f::new(1f32, 2f32);
        let b = 2f32;
        let mut c = Vector2::new(0f32, 0f32);

        a.mul_scalar_into(b, &mut c);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 4f32);
    }

    #[test]
    fn test_mul_vector() {
        let mut a = Vector2f::new(1f32, 2f32);
        let b = Vector2f::new(2f32, 3f32);

        a.mul_vector(&b);

        assert_eq!(a.x, 2f32);
        assert_eq!(a.y, 6f32);
    }

    #[test]
    fn test_mul_vector_into() {
        let a = Vector2f::new(1f32, 2f32);
        let b = Vector2f::new(2f32, 3f32);
        let mut c = Vector2::new(0f32, 0f32);

        a.mul_vector_into(&b, &mut c);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 6f32);
    }

    #[test]
    fn test_negate() {
        let mut a = Vector2f::new(1f32, 2f32);

        a.negate();

        assert_eq!(a.x, -1f32);
        assert_eq!(a.y, -2f32);
    }

    #[test]
    fn test_negate_into() {
        let a = Vector2f::new(1f32, 2f32);
        let mut b = Vector2f::new(0f32, 0f32);

        a.negate_into(&mut b);

        assert_eq!(b.x, -1f32);
        assert_eq!(b.y, -2f32);
    }

    #[test]
    fn test_normalize() {
        let mut a = Vector2f::new(1f32, 2f32);

        a.normalize();

        assert!((1f32 - a.length()).abs() < std::f32::EPSILON);
    }

    #[test]
    fn test_normalize_into() {
        let a = Vector2f::new(1f32, 2f32);
        let mut b = Vector2f::new(0f32, 0f32);

        a.normalize_into(&mut b);

        assert!((1f32 - b.length()).abs() < std::f32::EPSILON);
    }

    #[test]
    fn test_set() {
        let mut a = Vector2f::new(0f32, 0f32);
        let b = Vector2f::new(1f32, 2f32);

        a.set(&b);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
    }

    #[test]
    fn test_sub() {
        let mut a = Vector2f::new(2f32, 5f32);
        let b = Vector2f::new(1f32, 2f32);

        a.sub(&b);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 3f32);
    }

    #[test]
    fn test_sub_into() {
        let a = Vector2f::new(2f32, 5f32);
        let b = Vector2f::new(1f32, 2f32);
        let mut c = Vector2f::new(0f32, 0f32);

        a.sub_into(&b, &mut c);

        assert_eq!(c.x, 1f32);
        assert_eq!(c.y, 3f32);
    }

    #[test]
    fn test_zero() {
        let mut a = Vector2f::new(1f32, 2f32);

        a.zero();

        assert_eq!(a.x, 0f32);
        assert_eq!(a.y, 0f32);
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use xml::reader::{EventReader, XmlEvent, Error as XmlError};
use std;
use std::error::Error;

#[derive(Default)]
pub struct PropfindResponse {
    pub href: Option<String>,
}

#[derive(Eq, PartialEq, Debug)]
pub enum PropfindParseError {
    UnknownDocument,
    InvalidFieldValue,
    UnknownElement,
    UnknownField,
    ExpectedEndOfDocument,
    Xml(XmlError),
}

impl From<XmlError> for PropfindParseError {
    fn from(e: XmlError) -> Self {
        Error::Xml(e)
    }
}

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

impl Error for PropfindParseError {
    fn description(&self) -> &str {
        use PropfindParseError::*;
        match *self {
            UnknownDocument => "not a propfind response",
            InvalidFieldValue => "field must only contain text",
            UnknownElement => "document must only contain responses",
            UnkownField => "unsupported field",
            ExpectedEndOfDocument => "expected end of document",
            Xml(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        use PropfindParseError::*;
        match *self {
            Xml(ref e) => Some(e as &Error),
            _ => None,
        }
    }
}

pub fn parse_propfind<R: Read>(read: R) -> Result<Vec<PropfindResponse>, PropfindParseError> {
    enum Field {
        Href,
    }

    enum State {
        Items,
        Item {
            item: PropfindResponse,
            field: Option<Field>,
        },
        Start,
        End,
    }

    let parser = EventReader::new(read);
    let items = Vec::new();
    let mut state = State::Start;

    for e in parser {
        let e = try!(e);
        state = match state {
            State::Start => {
                match e {
                    XmlEvent::StartDocument { .. } => State::Start,
                    XmlEvent::StartElement { ref name, .. } if name.local_name == "multistatus" => {
                        State::Items
                    }
                    _ => return Err(PropfindParseError::UnknownDocument),
                }
            }
            State::End => {
                match e {
                    XmlEvent::EndDocument => return Ok(items),
                    _ => return Err(PropfindParseError::ExpectedEndOfDocument),
                }
            }
            State::Items => {
                match e {
                    XmlEvent::EndElement { .. } => State::End,
                    XmlEvent::StartElement { ref name, .. } if &*name.local_name == "response" => {
                        State::Item {
                            item: PropfindResponse::default(),
                            field: None,
                        }
                    }
                    _ => return Err(PropfindParseError::UnknownDocument),
                }
            }
            State::Item { field: None, item } => {
                match e {
                    XmlEvent::StartElement { name, .. } => {
                        match &*name.local_name {
                            "href" => {
                                State::Item {
                                    field: Some(Field::Href),
                                    item: item,
                                }
                            }
                            _ => {
                                State::Item {
                                    field: None,
                                    item: item,
                                }
                            }
                        }
                    }
                    XmlEvent::EndElement { .. } => {
                        items.push(item);
                        State::Items
                    }
                    _ => {
                        State::Item {
                            field: None,
                            item: item,
                        }
                    }
                }
            }
            State::Item { field: Some(field), mut item } => {
                match e {
                    XmlEvent::Characters(s) => {
                        match field {
                            Field::Href => item.href = Some(s),
                        };
                        State::Item {
                            field: Some(field),
                            item: item,
                        }
                    }
                    XmlEvent::EndElement { .. } => {
                        State::Item {
                            field: None,
                            item: item,
                        }
                    }
                    _ => return Err(PropfindParseError::InvalidFieldValue),
                }
            }
        }
    }
}
<commit_msg>fix build errors<commit_after>use std::io::Read;
use xml::reader::{EventReader, XmlEvent, Error as XmlError};
use std;
use std::error::Error;

#[derive(Default)]
pub struct PropfindResponse {
    pub href: Option<String>,
}

#[derive(Eq, PartialEq, Debug)]
pub enum PropfindParseError {
    UnknownDocument,
    InvalidFieldValue,
    UnknownElement,
    UnknownField,
    ExpectedEndOfDocument,
    Xml(XmlError),
}

impl From<XmlError> for PropfindParseError {
    fn from(e: XmlError) -> Self {
        PropfindParseError::Xml(e)
    }
}

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

impl Error for PropfindParseError {
    fn description(&self) -> &str {
        use self::PropfindParseError::*;
        match *self {
            UnknownDocument => "not a propfind response",
            InvalidFieldValue => "field must only contain text",
            UnknownElement => "document must only contain responses",
            UnknownField => "unsupported field",
            ExpectedEndOfDocument => "expected end of document",
            Xml(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        use self::PropfindParseError::*;
        match *self {
            Xml(ref e) => Some(e as &Error),
            _ => None,
        }
    }
}

pub fn parse_propfind<R: Read>(read: R) -> Result<Vec<PropfindResponse>, PropfindParseError> {
    enum Field {
        Href,
    }

    enum State {
        Items,
        Item {
            item: PropfindResponse,
            field: Option<Field>,
        },
        Start,
        End,
    }

    let parser = EventReader::new(read);
    let mut items = Vec::new();
    let mut state = State::Start;

    for e in parser {
        let e = try!(e);
        state = match state {
            State::Start => {
                match e {
                    XmlEvent::StartDocument { .. } => State::Start,
                    XmlEvent::StartElement { ref name, .. } if name.local_name == "multistatus" => {
                        State::Items
                    }
                    _ => return Err(PropfindParseError::UnknownDocument),
                }
            }
            State::End => {
                match e {
                    XmlEvent::EndDocument => return Ok(items),
                    _ => return Err(PropfindParseError::ExpectedEndOfDocument),
                }
            }
            State::Items => {
                match e {
                    XmlEvent::EndElement { .. } => State::End,
                    XmlEvent::StartElement { ref name, .. } if &*name.local_name == "response" => {
                        State::Item {
                            item: PropfindResponse::default(),
                            field: None,
                        }
                    }
                    _ => return Err(PropfindParseError::UnknownDocument),
                }
            }
            State::Item { field: None, item } => {
                match e {
                    XmlEvent::StartElement { name, .. } => {
                        match &*name.local_name {
                            "href" => {
                                State::Item {
                                    field: Some(Field::Href),
                                    item: item,
                                }
                            }
                            _ => {
                                State::Item {
                                    field: None,
                                    item: item,
                                }
                            }
                        }
                    }
                    XmlEvent::EndElement { .. } => {
                        items.push(item);
                        State::Items
                    }
                    _ => {
                        State::Item {
                            field: None,
                            item: item,
                        }
                    }
                }
            }
            State::Item { field: Some(field), mut item } => {
                match e {
                    XmlEvent::Characters(s) => {
                        match field {
                            Field::Href => item.href = Some(s),
                        };
                        State::Item {
                            field: Some(field),
                            item: item,
                        }
                    }
                    XmlEvent::EndElement { .. } => {
                        State::Item {
                            field: None,
                            item: item,
                        }
                    }
                    _ => return Err(PropfindParseError::InvalidFieldValue),
                }
            }
        }
    }

    Ok(items)
}
<|endoftext|>


<commit_before>/**
 * Reads NMEA messages from the GPS.
 */

use std::error::Error;
use std::mem::transmute;
use std::num::{Int, Float};

use telemetry::Degrees;
use telemetry::MetersPerSecond;

pub type Gravity = f32;
pub type MicroTesla = f32;
pub type Pascal = u32;
pub type Celsius = f32;

/**
 * GGA: Global positioning system fix data.
 */
#[derive(PartialEq)]
pub struct GgaMessage {
    pub latitude_degrees: f64,
    pub longitude_degrees: f64,
    pub horizontal_dilution_of_precision: f32,
}

/**
 * VTG: Course over ground and ground speed.
 */
#[derive(PartialEq)]
pub struct VtgMessage {
    pub course_d: Degrees,
    pub speed_m_s: MetersPerSecond,
}

#[derive(PartialEq)]
pub struct BinaryMessage {
    x_gravity: Gravity,
    y_gravity: Gravity,
    z_gravity: Gravity,
    x_magnetic_field: MicroTesla,
    y_magnetic_field: MicroTesla,
    z_magnetic_field: MicroTesla,
    pressure: Pascal,
    temperature: Celsius,
}

#[derive(PartialEq)]
pub enum NmeaMessage {
    Gga(GgaMessage),
    Vtg(VtgMessage),
    Binary(BinaryMessage),
}

macro_rules! bail_err {
    ($option:expr) => (
        match $option {
            Ok(s) => s,
            Err(e) => return Err(e.description().to_string()),
        };
    );
}
macro_rules! bail_none {
    ($option:expr) => (
        match $option {
            Some(s) => s,
            None => return Err("Message too short".to_string()),
        };
    );
}
macro_rules! convert {
    ($to:ty, $value:expr) => (
        unsafe {
            transmute::<u32, $to>(
                transmute::<_, u32>($value).to_le()
            )
        }
    )
}
macro_rules! array_to_type {
    ($to:ty, $array:expr) => (
        convert![$to, [$array[3], $array[2], $array[1], $array[0]]]
    )
}

impl NmeaMessage {
    fn parse(message: &str) -> Result<NmeaMessage, String> {
        if message.starts_with("$GPGGA") {
            // $GPGGA,hhmmss.sss,ddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,,,xxxx*hh<CR><LF>
            let mut iterator = message.split(',');

            iterator.next();  // Skip the message type
            iterator.next();  // Skip the timestamp since midnight UTC

            let latitude_degrees = {
                let string = bail_none!(iterator.next());
                let degrees: i32 = bail_err!(string[0..2].parse());
                let minutes: f64 = bail_err!(string[2..].parse());

                let north_indicator = bail_none!(iterator.next());
                let north = north_indicator == "N";
                let d = degrees as f64 + minutes / 60.0f64;
                if north { d } else { -d }
            };

            let longitude_degrees = {
                let string = bail_none!(iterator.next());
                let degrees: i32 = bail_err!(string[0..2].parse());
                let minutes: f64 = bail_err!(string[2..].parse());

                let east_indicator = bail_none!(iterator.next());
                let east = east_indicator == "E";
                let d = degrees as f64 + minutes / 60.0f64;
                if east { d } else { -d }
            };

            iterator.next();  // Skip the GPS quality indicator
            iterator.next();  // Skip the satellites used

            let hdop_str = bail_none!(iterator.next());
            let hdop: f32 = bail_err!(hdop_str.parse());

            Ok(
                NmeaMessage::Gga (
                    GgaMessage {
                        latitude_degrees: latitude_degrees,
                        longitude_degrees: longitude_degrees,
                        horizontal_dilution_of_precision: hdop,
                    }
                )
            )

        } else if message.starts_with("$GPVTG") {
            // GPVTG,x.x,T,x.x,M,x.x,N,x.x,K,a*hh<CR><LF>
            let mut iterator = message.split(',');

            iterator.next();  // Skip the message type

            let course_d_str = bail_none!(iterator.next());
            let course_d: f32 = bail_err!(course_d_str.parse());
            iterator.next();  // Skip the letter T indicating true course

            iterator.next();  // Skip the magnetic course
            iterator.next();  // Skip the letter M indicating magnetic course

            iterator.next();  // Skip speed in knots
            iterator.next();  // Skip the letter N indicating knots

            let speed_km_h_str = bail_none!(iterator.next());
            let speed_km_h: f32 = bail_err!(speed_km_h_str.parse());

            Ok(
                NmeaMessage::Vtg (
                    VtgMessage {
                        course_d: course_d,
                        speed_m_s: speed_km_h * 1000.0 / (60.0 * 60.0),
                    }
                )
            )
        } else {
            Err("Unknown NMEA message type".to_string())
        }
    }

    fn parse_binary(message: &[u8; 34]) -> Result<NmeaMessage, String> {
        // The payload length from the GPS is always 34 bytes
        unsafe {
            let acceleration_x: Gravity = array_to_type![f32, message[2..6]];
            let acceleration_y: Gravity = array_to_type![f32, message[6..10]];
            let acceleration_z: Gravity = array_to_type![f32, message[10..14]];
            let magnetic_x: MicroTesla = array_to_type![f32, message[14..18]];
            let magnetic_y: MicroTesla = array_to_type![f32, message[18..22]];
            let magnetic_z: MicroTesla = array_to_type![f32, message[22..26]];
            let pressure: Pascal = array_to_type![u32, message[26..30]];
            let temperature: Celsius = array_to_type![f32, message[30..34]];
            Ok(
                NmeaMessage::Binary (
                    BinaryMessage {
                        x_gravity: acceleration_x,
                        y_gravity: acceleration_y,
                        z_gravity: acceleration_z,
                        x_magnetic_field: magnetic_x,
                        y_magnetic_field: magnetic_y,
                        z_magnetic_field: magnetic_z,
                        pressure: pressure,
                        temperature: temperature,
                    }
                )
            )
        }
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::io::{BufRead, BufReader, Read};
    use std::mem::transmute;
    use std::num::{Int, Float};
    use std::path::Path;
    use super::{BinaryMessage, NmeaMessage, GgaMessage, VtgMessage};
    use super::NmeaMessage::{Binary, Gga, Vtg};
    use termios::{Speed, Termio};

    #[test]
    fn test_parse_gga() {
        let message = "$GPGGA,033403.456,0102.3456,N,0102.3456,W,1,11,0.8,108.2,M,,,,0000*01\r\n";
        let expected = GgaMessage {
            latitude_degrees: 1.0390933333333334f64,
            longitude_degrees: -1.0390933333333334f64,
            horizontal_dilution_of_precision: 0.8f32,
        };
        match NmeaMessage::parse(message).unwrap() {
            Gga(gga) => {
                assert!(expected == gga);
            }
            _ => assert!(false),
        }
    }

    #[test]
    fn test_parse_vtg() {
        // 36 km/h = 10 m/s
        let message = "$GPVTG,123.4,T,356.1,M,000.0,N,0036.0,K,A*32\r\n";
        let expected = VtgMessage {
            course_d: 123.4,
            speed_m_s: 10.0,
        };
        match NmeaMessage::parse(message).unwrap() {
            Vtg(vtg) => {
                assert!(expected == vtg);
            },
            _ => assert!(false),
        }
    }

    #[test]
    fn test_tty() {
        // This will fail on everything but the Pi, so let's just ignore it if we're not running on
        // the Pi.
        if !cfg!(target_arch = "arm") {
            return;
        }
        let mut tty = match File::open(Path::new("/dev/ttyAMA0")) {
            Ok(f) => f,
            Err(m) => panic!("Unable to open /dev/ttyAMA0."),
        };
        tty.set_speed(Speed::B1152000);
        tty.drop_input_output();
        let mut reader = BufReader::new(tty);
        let mut message = String::new();
        reader.read_line(&mut message);
        match NmeaMessage::parse(&message) {
            Ok(m) => (),
            Err(e) => panic!("Unable to parse NmeaMessage"),
        }
    }

    #[test]
    fn test_parse_binary() {
        let message: [u8; 34] = [
            0xCFu8, 0x01, 0xBD, 0x4F, 0xE1, 0x54, 0xBE, 0x15, 0xE9, 0xE2, 0x3F, 0x6F, 0x3C, 0xB4,
            0xC0, 0xC5, 0x9D, 0x2A, 0x40, 0x79, 0x84, 0x08, 0x40, 0xCE, 0xFA, 0xB0, 0x00, 0x01,
            0x85, 0xB1, 0x41, 0xF1, 0x99, 0x9A
        ];
        let x_gravity = convert![f32, 0xBD4FE154u32];
        let y_gravity = convert![f32, 0xBE15E9E2u32];
        let z_gravity = convert![f32, 0x3F6F3CB4u32];
        let x_magnetic_field = convert![f32, 0xC0C59D2Au32];
        let y_magnetic_field = convert![f32, 0x40798408u32];
        let z_magnetic_field = convert![f32, 0x40CEFAB0u32];
        let pressure = convert![u32, 0x000185B1u32];
        let temperature = convert![f32, 0x41F1999Au32];
        let expected = BinaryMessage {
            x_gravity: x_gravity,
            y_gravity: y_gravity,
            z_gravity: z_gravity,
            x_magnetic_field: x_magnetic_field,
            y_magnetic_field: y_magnetic_field,
            z_magnetic_field: z_magnetic_field,
            pressure: pressure,
            temperature: temperature,
        };
        match NmeaMessage::parse_binary(&message).unwrap() {
            Binary(binary) => {
                println!("x_gravity: expected {}, computed {}", expected.x_gravity, binary.x_gravity);
                assert!(binary == expected);
            },
            _ => assert!(false),
        }
    }

    #[test]
    fn test_convert() {
        println!("{}, {}", convert![f32, 0xBD4FE154u32], 0.93452);
        assert!((convert![f32, 0xBD4FE154u32] - -0.050752).abs() < 0.001);
    }
}
<commit_msg>Parse RMC messages<commit_after>/**
 * Reads NMEA messages from the GPS.
 */

use std::error::Error;
use std::mem::transmute;
use std::num::{Int, Float, ParseFloatError};

use telemetry::Degrees;
use telemetry::MetersPerSecond;

pub type Gravity = f32;
pub type MicroTesla = f32;
pub type Pascal = u32;
pub type Celsius = f32;

/**
 * GGA: Global positioning system fix data.
 */
#[derive(PartialEq)]
pub struct GgaMessage {
    pub latitude_degrees: f64,
    pub longitude_degrees: f64,
    pub horizontal_dilution_of_precision: f32,
}

/**
 * VTG: Course over ground and ground speed.
 */
#[derive(PartialEq)]
pub struct VtgMessage {
    pub course_d: Degrees,
    pub speed_m_s: MetersPerSecond,
}

/**
 * RMC: Recommended minimum specific GNSS data.
 */
#[derive(PartialEq)]
#[derive(Debug)]
pub struct RmcMessage {
    pub latitude_degrees: f64,
    pub longitude_degrees: f64,
    pub speed_m_s: MetersPerSecond,
    pub course_d: Degrees,
    pub magnetic_variation: Degrees,
}

#[derive(PartialEq)]
pub struct BinaryMessage {
    x_gravity: Gravity,
    y_gravity: Gravity,
    z_gravity: Gravity,
    x_magnetic_field: MicroTesla,
    y_magnetic_field: MicroTesla,
    z_magnetic_field: MicroTesla,
    pressure: Pascal,
    temperature: Celsius,
}

#[derive(PartialEq)]
pub enum NmeaMessage {
    Binary(BinaryMessage),
    Gga(GgaMessage),
    Vtg(VtgMessage),
    Rmc(RmcMessage),
}

macro_rules! bail_err {
    ($option:expr) => (
        match $option {
            Ok(s) => s,
            Err(e) => return Err(e.description().to_string())
        };
    );
}
macro_rules! bail_none {
    ($option:expr) => (
        match $option {
            Some(s) => s,
            None => return Err("Message too short".to_string())
        };
    );
}
macro_rules! convert {
    ($to:ty, $value:expr) => (
        unsafe {
            transmute::<u32, $to>(
                transmute::<_, u32>($value).to_le()
            )
        }
    )
}
macro_rules! array_to_type {
    ($to:ty, $array:expr) => (
        convert![$to, [$array[3], $array[2], $array[1], $array[0]]]
    )
}

impl NmeaMessage {
    fn parse(message: &str) -> Result<NmeaMessage, String> {
        // These if statements are sorted in the rough likelihood of appearance
        if message.starts_with("$GPGGA") {
            match NmeaMessage::parse_gga(message) {
                Ok(gga) => Ok(NmeaMessage::Gga(gga)),
                Err(e) => Err(e)
            }
        } else if message.starts_with("$GPVTG") {
            match NmeaMessage::parse_vtg(message) {
                Ok(vtg) => Ok(NmeaMessage::Vtg(vtg)),
                Err(e) => Err(e)
            }
        } else if message.starts_with("$GPRMC") {
            match NmeaMessage::parse_rmc(message) {
                Ok(rmc) => Ok(NmeaMessage::Rmc(rmc)),
                Err(e) => Err(e)
            }
        } else {
            Err("Unknown NMEA message type".to_string())
        }
    }

    /**
     * Time, position and fix related data for a GPS receiver.
     */
    fn parse_gga(message: &str) -> Result<GgaMessage, String> {
        // $GPGGA,hhmmss.sss,ddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,,,xxxx*hh<CR><LF>
        let mut iterator = message.split(',');

        iterator.next();  // Skip the message type
        iterator.next();  // Skip the UTC time

        let latitude_degrees = {
            let string = bail_none!(iterator.next());
            let d = bail_err!(NmeaMessage::parse_degrees_minutes(string));

            let north_indicator = bail_none!(iterator.next());
            let north = north_indicator == "N";
            if north { d } else { -d }
        };

        let longitude_degrees = {
            let string = bail_none!(iterator.next());
            let d = bail_err!(NmeaMessage::parse_degrees_minutes(string));

            let east_indicator = bail_none!(iterator.next());
            let east = east_indicator == "E";
            if east { d } else { -d }
        };

        let gps_quality_indicator = bail_none!(iterator.next());
        if gps_quality_indicator == "0" {
            return Err("Position fix unavailable".to_string());
        }
        iterator.next();  // Skip the satellites used

        let hdop_str = bail_none!(iterator.next());
        let hdop: f32 = bail_err!(hdop_str.parse());
        // Ignore altitude, DGPS station id, and checksum

        Ok(
            GgaMessage {
                latitude_degrees: latitude_degrees,
                longitude_degrees: longitude_degrees,
                horizontal_dilution_of_precision: hdop,
            }
        )
    }

    /**
     * The actual course and speed relative to the ground.
     */
    fn parse_vtg(message: &str) -> Result<VtgMessage, String> {
        // $GPVTG,x.x,T,x.x,M,x.x,N,x.x,K,a*hh<CR><LF>
        let mut iterator = message.split(',');

        iterator.next();  // Skip the message type

        let course_d_str = bail_none!(iterator.next());
        let course_d: f32 = bail_err!(course_d_str.parse());
        iterator.next();  // Skip the letter T indicating true course

        iterator.next();  // Skip the magnetic course
        iterator.next();  // Skip the letter M indicating magnetic course

        iterator.next();  // Skip speed in knots
        iterator.next();  // Skip the letter N indicating knots

        let speed_km_h_str = bail_none!(iterator.next());
        let speed_km_h: f32 = bail_err!(speed_km_h_str.parse());
        iterator.next();  // Skip the letter K indicating km/h

        let mode_and_checksum = bail_none!(iterator.next());
        if mode_and_checksum.starts_with("N") {
            return Err("Data not valid".to_string());
        }

        Ok(
            VtgMessage {
                course_d: course_d,
                speed_m_s: speed_km_h * 1000.0 / (60.0 * 60.0),
            }
        )
    }

    /**
     * Time, date, position, course and speed data.
     */
    fn parse_rmc(message: &str) -> Result<RmcMessage, String> {
        // $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,003.9,W,A*12<CR><LF>
        let mut iterator = message.split(',');

        iterator.next();  // Skip the message type
        iterator.next();  // Skip the UTC time

        let status = bail_none!(iterator.next());
        if status == "V" {
            return Err("Navigation receiver warning".to_string());
        }

        let latitude_degrees = {
            let string = bail_none!(iterator.next());
            let d = bail_err!(NmeaMessage::parse_degrees_minutes(string));

            let north_indicator = bail_none!(iterator.next());
            let north = north_indicator == "N";
            if north { d } else { -d }
        };

        let longitude_degrees = {
            let string = bail_none!(iterator.next());
            let d = bail_err!(NmeaMessage::parse_degrees_minutes(string));

            let east_indicator = bail_none!(iterator.next());
            let east = east_indicator == "E";
            if east { d } else { -d }
        };

        let speed_knots_str = bail_none!(iterator.next());
        let speed_knots: f32 = bail_err!(speed_knots_str.parse());
        let speed_m_s: MetersPerSecond = speed_knots * 0.5144;

        let course_d_str = bail_none!(iterator.next());
        let course: Degrees = bail_err!(course_d_str.parse());

        iterator.next();  // Skip UTC date

        let magnetic_variation = {
            let magnetic_d_str = bail_none!(iterator.next());
            let magnetic: Degrees = bail_err!(magnetic_d_str.parse());
            let east_west = bail_none!(iterator.next());
            if east_west == "E" { -magnetic } else { magnetic }
        };

        let mode_and_checksum = bail_none!(iterator.next());
        if mode_and_checksum.starts_with("N") {
            return Err("Data not valid".to_string());
        }

        Ok(
            RmcMessage {
                latitude_degrees: latitude_degrees,
                longitude_degrees: longitude_degrees,
                speed_m_s: speed_m_s,
                course_d: course,
                magnetic_variation: magnetic_variation,
            }
        )
    }

    fn parse_binary(message: &[u8; 34]) -> Result<NmeaMessage, String> {
        // The payload length from the GPS is always 34 bytes
        unsafe {
            let acceleration_x: Gravity = array_to_type![f32, message[2..6]];
            let acceleration_y: Gravity = array_to_type![f32, message[6..10]];
            let acceleration_z: Gravity = array_to_type![f32, message[10..14]];
            let magnetic_x: MicroTesla = array_to_type![f32, message[14..18]];
            let magnetic_y: MicroTesla = array_to_type![f32, message[18..22]];
            let magnetic_z: MicroTesla = array_to_type![f32, message[22..26]];
            let pressure: Pascal = array_to_type![u32, message[26..30]];
            let temperature: Celsius = array_to_type![f32, message[30..34]];
            Ok(
                NmeaMessage::Binary (
                    BinaryMessage {
                        x_gravity: acceleration_x,
                        y_gravity: acceleration_y,
                        z_gravity: acceleration_z,
                        x_magnetic_field: magnetic_x,
                        y_magnetic_field: magnetic_y,
                        z_magnetic_field: magnetic_z,
                        pressure: pressure,
                        temperature: temperature,
                    }
                )
            )
        }
    }

    fn parse_degrees_minutes(degrees_minutes: &str) -> Result<f64, ParseFloatError> {
        let decimal_point_index = match degrees_minutes.chars().position(|x| x == '.') {
            Some(index) => index,
            None => return degrees_minutes.parse::<f64>()
        };
        // There are always two digits for whole number minutes
        let degrees: f64 = match degrees_minutes[0..decimal_point_index - 2].parse() {
            Ok(i) => i,
            Err(e) => return Err(e)
        };
        let minutes: f64 = match degrees_minutes[decimal_point_index - 2..].parse() {
            Ok(f) => f,
            Err(e) => return Err(e)
        };
        Ok(degrees as f64 + minutes / 60.0f64)
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::io::{BufRead, BufReader, Read};
    use std::mem::transmute;
    use std::num::{Int, Float};
    use std::path::Path;
    use super::{BinaryMessage, GgaMessage, NmeaMessage, RmcMessage, VtgMessage};
    use super::NmeaMessage::{Binary, Gga, Vtg};
    use termios::{Speed, Termio};

    #[test]
    fn test_parse_gga() {
        let message = "$GPGGA,033403.456,0102.3456,N,0102.3456,W,1,11,0.8,108.2,M,,,,0000*01\r\n";
        let expected = GgaMessage {
            latitude_degrees: 1.0390933333333334f64,
            longitude_degrees: -1.0390933333333334f64,
            horizontal_dilution_of_precision: 0.8f32,
        };
        match NmeaMessage::parse_gga(message) {
            Ok(gga) => assert!(expected == gga),
            _ => assert!(false)
        }
    }

    #[test]
    fn test_parse_vtg() {
        // 36 km/h = 10 m/s
        let message = "$GPVTG,123.4,T,356.1,M,000.0,N,0036.0,K,A*32\r\n";
        let expected = VtgMessage {
            course_d: 123.4,
            speed_m_s: 10.0,
        };
        match NmeaMessage::parse_vtg(message) {
            Ok(vtg) => assert!(expected == vtg),
            _ => assert!(false)
        }
    }

    #[test]
    fn test_parse_rmc() {
        let message = "$GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,003.9,W,A*12\r\n";
        let expected = RmcMessage {
            latitude_degrees: 24.784915,
            longitude_degrees: 121.008705,
            speed_m_s: 0.0,
            course_d: 0.0,
            magnetic_variation: 3.9,
        };
        match NmeaMessage::parse_rmc(message) {
            Ok(rmc) => {
                println!("{:?}", expected);
                println!("{:?}", rmc);
                assert!(expected == rmc);
            }
            _ => assert!(false),
        }
    }

    #[test]
    fn test_parse() {
        let gga = "$GPGGA,033403.456,0102.3456,N,0102.3456,W,1,11,0.8,108.2,M,,,,0000*01\r\n";
        let vtg = "$GPVTG,123.4,T,356.1,M,000.0,N,0036.0,K,A*32\r\n";
        let rmc = "$GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,003.9,W,A*12\r\n";

        match NmeaMessage::parse(gga).unwrap() {
            NmeaMessage::Gga(gga) => (),
            _ => assert!(false)
        };
        match NmeaMessage::parse(vtg).unwrap() {
            NmeaMessage::Vtg(vtg) => (),
            _ => assert!(false)
        };
        match NmeaMessage::parse(rmc).unwrap() {
            NmeaMessage::Rmc(rmc) => (),
            _ => assert!(false)
        };
    }

    #[test]
    fn test_tty() {
        return;
        // This will fail on everything but the Pi, so let's just ignore it if we're not running on
        // the Pi.
        if !cfg!(target_arch = "arm") {
            return;
        }
        let mut tty = match File::open(Path::new("/dev/ttyAMA0")) {
            Ok(f) => f,
            Err(m) => panic!("Unable to open /dev/ttyAMA0.")
        };
        tty.set_speed(Speed::B1152000);
        tty.drop_input_output();
        let mut reader = BufReader::new(tty);
        let mut message = String::new();
        reader.read_line(&mut message);
        match NmeaMessage::parse(&message) {
            Ok(m) => (),
            Err(e) => panic!("Unable to parse NmeaMessage")
        }
    }

    #[test]
    fn test_parse_binary() {
        let message: [u8; 34] = [
            0xCFu8, 0x01, 0xBD, 0x4F, 0xE1, 0x54, 0xBE, 0x15, 0xE9, 0xE2, 0x3F, 0x6F, 0x3C, 0xB4,
            0xC0, 0xC5, 0x9D, 0x2A, 0x40, 0x79, 0x84, 0x08, 0x40, 0xCE, 0xFA, 0xB0, 0x00, 0x01,
            0x85, 0xB1, 0x41, 0xF1, 0x99, 0x9A
        ];
        let x_gravity = convert![f32, 0xBD4FE154u32];
        let y_gravity = convert![f32, 0xBE15E9E2u32];
        let z_gravity = convert![f32, 0x3F6F3CB4u32];
        let x_magnetic_field = convert![f32, 0xC0C59D2Au32];
        let y_magnetic_field = convert![f32, 0x40798408u32];
        let z_magnetic_field = convert![f32, 0x40CEFAB0u32];
        let pressure = convert![u32, 0x000185B1u32];
        let temperature = convert![f32, 0x41F1999Au32];
        let expected = BinaryMessage {
            x_gravity: x_gravity,
            y_gravity: y_gravity,
            z_gravity: z_gravity,
            x_magnetic_field: x_magnetic_field,
            y_magnetic_field: y_magnetic_field,
            z_magnetic_field: z_magnetic_field,
            pressure: pressure,
            temperature: temperature,
        };
        match NmeaMessage::parse_binary(&message).unwrap() {
            Binary(binary) => assert!(binary == expected),
            _ => assert!(false)
        }
    }

    #[test]
    fn test_convert() {
        assert!((convert![f32, 0xBD4FE154u32] - -0.050752).abs() < 0.001);
    }
}
<|endoftext|>


<commit_before>#![crate_name="world"]
#![feature(unboxed_closures)]
#![allow(unstable)]

extern crate rand;
extern crate "rustc-serialize" as rustc_serialize;
extern crate num;
extern crate collect;
extern crate "calx_util" as util;

pub use entity::{Entity};
pub use flags::{camera, set_camera, get_tick};
pub use fov::{Fov};
pub use geom::{HexGeom};
pub use location::{Location, Chart, Unchart};
pub use msg::{pop_msg};
pub use terrain::{TerrainType};
pub use world::{init_world, load, save};
pub use dir6::Dir6;

macro_rules! msg(
    ($($arg:tt)*) => ( ::msg::push_msg(::Msg::Text(format!($($arg)*))))
);

macro_rules! msgln(
    ($($arg:tt)*) => ({
        ::msg::push_msg(::Msg::Text(format!($($arg)*)));
        ::msg::push_msg(::Msg::Text("\n".to_string()));
    })
);

macro_rules! caption(
    ($($arg:tt)*) => ( ::msg::push_msg(::Msg::Caption(format!($($arg)*))))
);

pub mod action;
pub mod components;
pub mod item;

mod ability;
mod area;
mod component_ref;
mod dir6;
mod ecs;
mod entity;
mod flags;
mod fov;
mod geom;
mod geomorph;
mod geomorph_data;
mod location;
mod mapgen;
mod msg;
mod prototype;
mod rng;
mod spatial;
mod spawn;
mod stats;
mod terrain;
mod world;

#[derive(Copy, Eq, PartialEq, Show)]
pub enum FovStatus {
    Seen,
    Remembered,
}

/// Landscape type. Also serves as bit field in order to produce habitat masks
/// for entity spawning etc.
#[derive(Copy, Eq, PartialEq, Clone, Show, RustcEncodable, RustcDecodable)]
pub enum Biome {
    Overland = 0b1,
    Dungeon  = 0b10,

    // For things showing up at a biome.
    Anywhere = -1,
}

impl Biome {
    pub fn default_terrain(self) -> terrain::TerrainType {
        match self {
            Biome::Overland => TerrainType::Tree,
            Biome::Dungeon => TerrainType::Rock,
            _ => TerrainType::Void,
        }
    }
}

#[derive(Copy, Eq, PartialEq, Show, Clone, RustcEncodable, RustcDecodable)]
pub struct AreaSpec {
    pub biome: Biome,
    pub depth: i32,
}

impl AreaSpec {
    pub fn new(biome: Biome, depth: i32) -> AreaSpec {
        AreaSpec { biome: biome, depth: depth }
    }

    /// Return whether a thing with this spec can be spawned in an environment
    /// with the given spec.
    pub fn can_hatch_in(&self, environment: &AreaSpec) -> bool {
        self.depth >= 0 && self.depth <= environment.depth &&
        (self.biome as i32 & environment.biome as i32) != 0
    }
}

/// Various one-off signals the game sends to the UI layer.
#[derive(Clone, Show)]
pub enum Msg {
    /// Regular event message
    Text(String),
    /// Important event message to the center of the screen
    Caption(String),
    // TODO: Type of effect.
    Explosion(Location),
    Damage(Entity),
    Gib(Location),
}

/// Light level value.
#[derive(Copy, Show, RustcEncodable, RustcDecodable)]
pub struct Light {
    lum: f32,
}

impl Light {
    pub fn new(lum: f32) -> Light {
        assert!(lum >= 0.0 && lum <= 2.0);
        Light { lum: lum }
    }

    pub fn apply(&self, color: &util::Rgb) -> util::Rgb {
        if self.lum <= 1.0 {
            // Make the darkness blue instead of totally black.
            util::Rgb::new(
                (color.r as f32 * self.lum) as u8,
                (color.g as f32 * util::clamp(0.0, 1.0, self.lum + 0.2)) as u8,
                (color.b as f32 * util::clamp(0.0, 1.0, self.lum + 0.4)) as u8)
        } else {
            util::Rgb::new(
                255 - ((255 - color.r) as f32 * (2.0 - self.lum)) as u8,
                255 - ((255 - color.g) as f32 * (2.0 - self.lum)) as u8,
                255 - ((255 - color.b) as f32 * (2.0 - self.lum)) as u8)
        }
    }
}
<commit_msg>Retain a bit of red too so that nothing goes entirely black<commit_after>#![crate_name="world"]
#![feature(unboxed_closures)]
#![allow(unstable)]

extern crate rand;
extern crate "rustc-serialize" as rustc_serialize;
extern crate num;
extern crate collect;
extern crate "calx_util" as util;

pub use entity::{Entity};
pub use flags::{camera, set_camera, get_tick};
pub use fov::{Fov};
pub use geom::{HexGeom};
pub use location::{Location, Chart, Unchart};
pub use msg::{pop_msg};
pub use terrain::{TerrainType};
pub use world::{init_world, load, save};
pub use dir6::Dir6;

macro_rules! msg(
    ($($arg:tt)*) => ( ::msg::push_msg(::Msg::Text(format!($($arg)*))))
);

macro_rules! msgln(
    ($($arg:tt)*) => ({
        ::msg::push_msg(::Msg::Text(format!($($arg)*)));
        ::msg::push_msg(::Msg::Text("\n".to_string()));
    })
);

macro_rules! caption(
    ($($arg:tt)*) => ( ::msg::push_msg(::Msg::Caption(format!($($arg)*))))
);

pub mod action;
pub mod components;
pub mod item;

mod ability;
mod area;
mod component_ref;
mod dir6;
mod ecs;
mod entity;
mod flags;
mod fov;
mod geom;
mod geomorph;
mod geomorph_data;
mod location;
mod mapgen;
mod msg;
mod prototype;
mod rng;
mod spatial;
mod spawn;
mod stats;
mod terrain;
mod world;

#[derive(Copy, Eq, PartialEq, Show)]
pub enum FovStatus {
    Seen,
    Remembered,
}

/// Landscape type. Also serves as bit field in order to produce habitat masks
/// for entity spawning etc.
#[derive(Copy, Eq, PartialEq, Clone, Show, RustcEncodable, RustcDecodable)]
pub enum Biome {
    Overland = 0b1,
    Dungeon  = 0b10,

    // For things showing up at a biome.
    Anywhere = -1,
}

impl Biome {
    pub fn default_terrain(self) -> terrain::TerrainType {
        match self {
            Biome::Overland => TerrainType::Tree,
            Biome::Dungeon => TerrainType::Rock,
            _ => TerrainType::Void,
        }
    }
}

#[derive(Copy, Eq, PartialEq, Show, Clone, RustcEncodable, RustcDecodable)]
pub struct AreaSpec {
    pub biome: Biome,
    pub depth: i32,
}

impl AreaSpec {
    pub fn new(biome: Biome, depth: i32) -> AreaSpec {
        AreaSpec { biome: biome, depth: depth }
    }

    /// Return whether a thing with this spec can be spawned in an environment
    /// with the given spec.
    pub fn can_hatch_in(&self, environment: &AreaSpec) -> bool {
        self.depth >= 0 && self.depth <= environment.depth &&
        (self.biome as i32 & environment.biome as i32) != 0
    }
}

/// Various one-off signals the game sends to the UI layer.
#[derive(Clone, Show)]
pub enum Msg {
    /// Regular event message
    Text(String),
    /// Important event message to the center of the screen
    Caption(String),
    // TODO: Type of effect.
    Explosion(Location),
    Damage(Entity),
    Gib(Location),
}

/// Light level value.
#[derive(Copy, Show, RustcEncodable, RustcDecodable)]
pub struct Light {
    lum: f32,
}

impl Light {
    pub fn new(lum: f32) -> Light {
        assert!(lum >= 0.0 && lum <= 2.0);
        Light { lum: lum }
    }

    pub fn apply(&self, color: &util::Rgb) -> util::Rgb {
        if self.lum <= 1.0 {
            // Make the darkness blue instead of totally black.
            util::Rgb::new(
                (color.r as f32 * util::clamp(0.0, 1.0, self.lum + 0.125)) as u8,
                (color.g as f32 * util::clamp(0.0, 1.0, self.lum + 0.25)) as u8,
                (color.b as f32 * util::clamp(0.0, 1.0, self.lum + 0.5)) as u8)
        } else {
            util::Rgb::new(
                255 - ((255 - color.r) as f32 * (2.0 - self.lum)) as u8,
                255 - ((255 - color.g) as f32 * (2.0 - self.lum)) as u8,
                255 - ((255 - color.b) as f32 * (2.0 - self.lum)) as u8)
        }
    }
}
<|endoftext|>


<commit_before>use winit::{
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    platform::desktop::EventLoopExtDesktop,
    window::WindowBuilder,
};

fn main() {
    let mut event_loop = EventLoop::new();

    let window = WindowBuilder::new()
        .with_title("A fantastic window!")
        .build(&event_loop)
        .unwrap();

    println!("Close the window to continue.");
    event_loop.run_return(|event, _, control_flow| match event {
        Event::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } => *control_flow = ControlFlow::Exit,
        _ => *control_flow = ControlFlow::Wait,
    });
    drop(window);

    let _window_2 = WindowBuilder::new()
        .with_title("A second, fantasticer window!")
        .build(&event_loop)
        .unwrap();

    println!("Wa ha ha! You thought that closing the window would finish this?!");
    event_loop.run_return(|event, _, control_flow| match event {
        Event::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } => *control_flow = ControlFlow::Exit,
        _ => *control_flow = ControlFlow::Wait,
    });

    println!("Okay we're done now for real.");
}
<commit_msg>Fix run_return example build error on non-desktop platforms (#1067)<commit_after>// Limit this example to only compatible platforms.
#[cfg(any(
    target_os = "windows",
    target_os = "macos",
    target_os = "linux",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "netbsd",
    target_os = "openbsd"
))]
fn main() {
    use winit::{
        event::{Event, WindowEvent},
        event_loop::{ControlFlow, EventLoop},
        platform::desktop::EventLoopExtDesktop,
        window::WindowBuilder,
    };

    let mut event_loop = EventLoop::new();

    let window = WindowBuilder::new()
        .with_title("A fantastic window!")
        .build(&event_loop)
        .unwrap();

    println!("Close the window to continue.");
    event_loop.run_return(|event, _, control_flow| match event {
        Event::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } => *control_flow = ControlFlow::Exit,
        _ => *control_flow = ControlFlow::Wait,
    });
    drop(window);

    let _window_2 = WindowBuilder::new()
        .with_title("A second, fantasticer window!")
        .build(&event_loop)
        .unwrap();

    println!("Wa ha ha! You thought that closing the window would finish this?!");
    event_loop.run_return(|event, _, control_flow| match event {
        Event::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } => *control_flow = ControlFlow::Exit,
        _ => *control_flow = ControlFlow::Wait,
    });

    println!("Okay we're done now for real.");
}

#[cfg(any(target_os = "ios", target_os = "android", target_os = "emscripten"))]
fn main() {
    println!("This platform doesn't support run_return.");
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! storage_value {
    ($name:ident {
        const SIZE = $body:expr;

        $($field_name:ident : $field_type:ty [$from:expr => $to:expr])*
    }) => (
        #[derive(Clone, PartialEq)]
        pub struct $name {
            raw: Vec<u8>
        }

        impl<'a> $crate::messages::Field<'a> for $name {
            fn read(buffer: &'a [u8], from: usize, to: usize) -> Self {
                let vec: Vec<u8> = $crate::messages::Field::read(buffer, from, to);
                $crate::storage::StorageValue::deserialize(vec)
            }

            fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
                $crate::messages::Field::write(&self.raw, buffer, from, to);
            }

            fn check(buffer: &'a [u8], from: usize, to: usize) -> Result<(), $crate::messages::Error> {

                let raw_message: $crate::messages::RawMessage = $crate::messages::Field::read(buffer, from, to);
                $(raw_message.check::<$field_type>($from, $to)?;)*
                Ok(())
            }

            fn field_size() -> usize {
                1
            }
        }

        impl $crate::storage::StorageValue for $name {
            fn serialize(self) -> Vec<u8> {
                self.raw
            }

            fn deserialize(v: Vec<u8>) -> Self {
                $name {
                    raw: v
                }
            }

            fn hash(&self) -> Hash {
                $name::hash(self)
            }
        }

        // TODO extract some fields like hash and from_raw into trait
        impl $name {
            pub fn new($($field_name: $field_type,)*) -> $name {
                use $crate::messages::{Field};
                let mut buf = vec![0; $body];
                $($field_name.write(&mut buf, $from, $to);)*
                $name { raw: buf }
            }

            pub fn from_raw(raw: Vec<u8>) -> $name {
                debug_assert_eq!(raw.len(), $body);
                $ name { raw: raw }
            }

            pub fn hash(&self) -> Hash {
                hash(self.raw.as_ref())
            }

            $(pub fn $field_name(&self) -> $field_type {
                use $crate::messages::Field;
                Field::read(&self.raw, $from, $to)
            })*
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> Result<(), ::std::fmt::Error> {
                fmt.debug_struct(stringify!($name))
                 $(.field(stringify!($field_name), &self.$field_name()))*
                   .finish()
            }
        }
    )
}
<commit_msg>Fixed Field::check inside of macro_rules storage_value!<commit_after>#[macro_export]
macro_rules! storage_value {
    ($name:ident {
        const SIZE = $body:expr;

        $($field_name:ident : $field_type:ty [$from:expr => $to:expr])*
    }) => (
        #[derive(Clone, PartialEq)]
        pub struct $name {
            raw: Vec<u8>
        }

        impl<'a> $crate::messages::Field<'a> for $name {
            fn read(buffer: &'a [u8], from: usize, to: usize) -> Self {
                let vec: Vec<u8> = $crate::messages::Field::read(buffer, from, to);
                $crate::storage::StorageValue::deserialize(vec)
            }

            fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
                $crate::messages::Field::write(&self.raw, buffer, from, to);
            }

            fn check(buffer: &'a [u8], from_st_val: usize, to_st_val: usize) -> Result<(), $crate::messages::Error> {

                <Vec<u8> as $crate::messages::Field>::check(buffer, from_st_val, to_st_val)?;
                let vec: Vec<u8> = $crate::messages::Field::read(buffer, from_st_val, to_st_val);
                $( <$field_type as $crate::messages::Field>::check(&vec, $from, $to)?;)*
                //$(raw_message.check::<$field_type>($from, $to)?;)*
                Ok(())
            }

            fn field_size() -> usize {
                1
            }
        }

        impl $crate::storage::StorageValue for $name {
            fn serialize(self) -> Vec<u8> {
                self.raw
            }

            fn deserialize(v: Vec<u8>) -> Self {
                $name {
                    raw: v
                }
            }

            fn hash(&self) -> Hash {
                $name::hash(self)
            }
        }

        // TODO extract some fields like hash and from_raw into trait
        impl $name {
            pub fn new($($field_name: $field_type,)*) -> $name {
                use $crate::messages::{Field};
                let mut buf = vec![0; $body];
                $($field_name.write(&mut buf, $from, $to);)*
                $name { raw: buf }
            }

            pub fn from_raw(raw: Vec<u8>) -> $name {
                debug_assert_eq!(raw.len(), $body);
                $ name { raw: raw }
            }

            pub fn hash(&self) -> Hash {
                hash(self.raw.as_ref())
            }

            $(pub fn $field_name(&self) -> $field_type {
                use $crate::messages::Field;
                Field::read(&self.raw, $from, $to)
            })*
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> Result<(), ::std::fmt::Error> {
                fmt.debug_struct(stringify!($name))
                 $(.field(stringify!($field_name), &self.$field_name()))*
                   .finish()
            }
        }
    )
}
<|endoftext|>