<commit_before>use super::{Simd, SimdFrom};
use numbers::*;
use simd::x86::sse2::*;
use simd::*;
use std::arch::x86_64::*;
use std::mem;

/// This value must be read in groups of 2 bits:
/// 10 means that the third position (since it's the third bit pair)
/// will be replaced with the value of the second position (10b = 2d)
const SWAP_IQ_PS: i32 = 0b1011_0001;

impl Simd<f32> for f32x4 {
    type Array = [f32; 4];

    #[inline]
    fn to_array(self) -> Self::Array {
        let mut target = [0.0; 4];
        self.store(&mut target, 0);
        target
    }

    type ComplexArray = [Complex<f32>; 2];

    const LEN: usize = 4;

    #[inline]
    fn load_wrap_unchecked(array: &[f32], idx: usize) -> f32x4 {
        let mut temp = [0.0; 4];
        for (i, t) in temp.iter_mut().enumerate() {
            *t = unsafe { *array.get_unchecked((idx + i) % array.len()) };
        }
        f32x4::load(&temp, 0)
    }

    #[inline]
    fn from_complex(value: Complex<f32>) -> f32x4 {
        f32x4::new(value.re, value.im, value.re, value.im)
    }

    #[inline]
    fn add_real(self, value: f32) -> f32x4 {
        let increment = f32x4::splat(value);
        self + increment
    }

    #[inline]
    fn add_complex(self, value: Complex<f32>) -> f32x4 {
        let increment = f32x4::new(value.re, value.im, value.re, value.im);
        self + increment
    }

    #[inline]
    fn scale_real(self, value: f32) -> f32x4 {
        let scale_vector = f32x4::splat(value);
        self * scale_vector
    }

    #[inline]
    fn scale_complex(self, value: Complex<f32>) -> f32x4 {
        let scaling_real = f32x4::splat(value.re);
        let scaling_imag = f32x4::splat(value.im);
        let parallel = scaling_real * self;
        let shuffled = self.swap_iq();
        let cross = scaling_imag * shuffled;
        unsafe {
            mem::transmute(_mm_addsub_ps(
                mem::transmute(parallel),
                mem::transmute(cross),
            ))
        }
    }

    #[inline]
    fn mul_complex(self, value: f32x4) -> f32x4 {
        let scaling_real = f32x4::new(
            value.extract(0),
            value.extract(0),
            value.extract(2),
            value.extract(2),
        );

        let scaling_imag = f32x4::new(
            value.extract(1),
            value.extract(1),
            value.extract(3),
            value.extract(3),
        );

        let parallel = scaling_real * self;
        let shuffled = self.swap_iq();
        let cross = scaling_imag * shuffled;
        unsafe {
            mem::transmute(_mm_addsub_ps(
                mem::transmute(parallel),
                mem::transmute(cross),
            ))
        }
    }

    #[inline]
    fn div_complex(self, value: f32x4) -> f32x4 {
        let scaling_imag = f32x4::new(
            self.extract(0),
            self.extract(0),
            self.extract(2),
            self.extract(2),
        );

        let scaling_real = f32x4::new(
            self.extract(1),
            self.extract(1),
            self.extract(3),
            self.extract(3),
        );

        let parallel = scaling_real * value;
        let shuffled = value.swap_iq();
        let cross = scaling_imag * shuffled;
        let mul: f32x4 = unsafe {
            mem::transmute(_mm_addsub_ps(
                mem::transmute(parallel),
                mem::transmute(cross),
            ))
        };
        let square = shuffled * shuffled;
        let square_shuffled = square.swap_iq();
        let sum = square + square_shuffled;
        let div = mul / sum;
        div.swap_iq()
    }

    #[inline]
    fn complex_abs_squared(self) -> f32x4 {
        let squared = self * self;
        unsafe {
            mem::transmute(_mm_hadd_ps(
                mem::transmute(squared),
                mem::transmute(squared),
            ))
        }
    }

    #[inline]
    fn complex_abs(self) -> f32x4 {
        let squared_sum = self.complex_abs_squared();
        squared_sum.sqrt()
    }

    #[inline]
    fn sqrt(self) -> f32x4 {
        self.sqrt()
    }

    #[inline]
    fn store_half_unchecked(self, target: &mut [f32], index: usize) {
        unsafe {
            *target.get_unchecked_mut(index) = self.extract(0);
            *target.get_unchecked_mut(index + 1) = self.extract(1);
        }
    }

    #[inline]
    fn sum_real(&self) -> f32 {
        self.extract(0) + self.extract(1) + self.extract(2) + self.extract(3)
    }

    #[inline]
    fn sum_complex(&self) -> Complex<f32> {
        Complex::<f32>::new(
            self.extract(0) + self.extract(2),
            self.extract(1) + self.extract(3),
        )
    }

    #[inline]
    fn max(self, other: Self) -> Self {
        self.max(other)
    }

    #[inline]
    fn min(self, other: Self) -> Self {
        self.min(other)
    }

    #[inline]
    fn swap_iq(self) -> Self {
        unsafe { mem::transmute(_mm_permute_ps(mem::transmute(self), SWAP_IQ_PS)) }
    }
}

impl Simd<f64> for f64x2 {
    type Array = [f64; 2];

    #[inline]
    fn to_array(self) -> Self::Array {
        let mut target = [0.0; 2];
        self.store(&mut target, 0);
        target
    }

    type ComplexArray = [Complex<f64>; 1];

    const LEN: usize = 2;

    #[inline]
    fn load_wrap_unchecked(array: &[f64], idx: usize) -> f64x2 {
        let mut temp = [0.0; 2];
        for (i, t) in temp.iter_mut().enumerate() {
            *t = unsafe { *array.get_unchecked((idx + i) % array.len()) };
        }

        f64x2::load(&temp, 0)
    }

    #[inline]
    fn from_complex(value: Complex<f64>) -> f64x2 {
        f64x2::new(value.re, value.im)
    }

    #[inline]
    fn add_real(self, value: f64) -> f64x2 {
        let increment = f64x2::splat(value);
        self + increment
    }

    #[inline]
    fn add_complex(self, value: Complex<f64>) -> f64x2 {
        let increment = f64x2::new(value.re, value.im);
        self + increment
    }

    #[inline]
    fn scale_real(self, value: f64) -> f64x2 {
        let scale_vector = f64x2::splat(value);
        self * scale_vector
    }

    #[inline]
    fn scale_complex(self, value: Complex<f64>) -> f64x2 {
        let complex = Complex::new(self.extract(0), self.extract(1));
        let result = complex * value;
        f64x2::new(result.re, result.im)
    }

    #[inline]
    fn mul_complex(self, value: f64x2) -> f64x2 {
        let complex = Complex::new(self.extract(0), self.extract(1));
        let value = Complex::new(value.extract(0), value.extract(1));
        let result = complex * value;
        f64x2::new(result.re, result.im)
    }

    #[inline]
    fn div_complex(self, value: f64x2) -> f64x2 {
        let complex = Complex::new(self.extract(0), self.extract(1));
        let value = Complex::new(value.extract(0), value.extract(1));
        let result = complex / value;
        f64x2::new(result.re, result.im)
    }

    #[inline]
    fn complex_abs_squared(self) -> f64x2 {
        let a = self.extract(0);
        let b = self.extract(1);
        let result = a * a + b * b;
        f64x2::new(result, 0.0)
    }

    #[inline]
    fn complex_abs(self) -> f64x2 {
        let a = self.extract(0);
        let b = self.extract(1);
        let result = (a * a + b * b).sqrt();
        f64x2::new(result, 0.0)
    }

    #[inline]
    fn sqrt(self) -> f64x2 {
        simd::x86::sse2::Sse2F64x2::sqrt(self)
    }

    #[inline]
    fn store_half_unchecked(self, target: &mut [f64], index: usize) {
        unsafe {
            *target.get_unchecked_mut(index) = self.extract(0);
        }
    }

    #[inline]
    fn sum_real(&self) -> f64 {
        self.extract(0) + self.extract(1)
    }

    #[inline]
    fn sum_complex(&self) -> Complex<f64> {
        Complex::<f64>::new(self.extract(0), self.extract(1))
    }

    #[inline]
    fn max(self, other: Self) -> Self {
        simd::x86::sse2::Sse2F64x2::max(self, other)
    }

    #[inline]
    fn min(self, other: Self) -> Self {
        simd::x86::sse2::Sse2F64x2::min(self, other)
    }

    #[inline]
    fn swap_iq(self) -> Self {
        f64x2::new(self.extract(1), self.extract(0))
    }
}

impl SimdFrom<f32x4> for i32x4 {
    fn regfrom(value: f32x4) -> Self {
        value.to_i32()
    }
}

impl SimdFrom<i32x4> for f32x4 {
    fn regfrom(value: i32x4) -> Self {
        value.to_f32()
    }
}

impl SimdFrom<f64x2> for i64x2 {
    fn regfrom(value: f64x2) -> Self {
        value.to_i64()
    }
}

impl SimdFrom<i64x2> for f64x2 {
    fn regfrom(value: i64x2) -> Self {
        value.to_f64()
    }
}

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

    #[test]
    fn shuffle_test() {
        let vec = f32x4::new(1.0, 2.0, 3.0, 4.0);
        let result = vec.swap_iq();
        assert_eq!(result.extract(0), vec.extract(1));
        assert_eq!(result.extract(1), vec.extract(0));
        assert_eq!(result.extract(2), vec.extract(3));
        assert_eq!(result.extract(3), vec.extract(2));
    }
}
<commit_msg>Fixed another build error<commit_after>use super::{Simd, SimdFrom};
use numbers::*;
use simd::x86::sse2::*;
use simd::*;
use simd;
use std::arch::x86_64::*;
use std::mem;

/// This value must be read in groups of 2 bits:
/// 10 means that the third position (since it's the third bit pair)
/// will be replaced with the value of the second position (10b = 2d)
const SWAP_IQ_PS: i32 = 0b1011_0001;

impl Simd<f32> for f32x4 {
    type Array = [f32; 4];

    #[inline]
    fn to_array(self) -> Self::Array {
        let mut target = [0.0; 4];
        self.store(&mut target, 0);
        target
    }

    type ComplexArray = [Complex<f32>; 2];

    const LEN: usize = 4;

    #[inline]
    fn load_wrap_unchecked(array: &[f32], idx: usize) -> f32x4 {
        let mut temp = [0.0; 4];
        for (i, t) in temp.iter_mut().enumerate() {
            *t = unsafe { *array.get_unchecked((idx + i) % array.len()) };
        }
        f32x4::load(&temp, 0)
    }

    #[inline]
    fn from_complex(value: Complex<f32>) -> f32x4 {
        f32x4::new(value.re, value.im, value.re, value.im)
    }

    #[inline]
    fn add_real(self, value: f32) -> f32x4 {
        let increment = f32x4::splat(value);
        self + increment
    }

    #[inline]
    fn add_complex(self, value: Complex<f32>) -> f32x4 {
        let increment = f32x4::new(value.re, value.im, value.re, value.im);
        self + increment
    }

    #[inline]
    fn scale_real(self, value: f32) -> f32x4 {
        let scale_vector = f32x4::splat(value);
        self * scale_vector
    }

    #[inline]
    fn scale_complex(self, value: Complex<f32>) -> f32x4 {
        let scaling_real = f32x4::splat(value.re);
        let scaling_imag = f32x4::splat(value.im);
        let parallel = scaling_real * self;
        let shuffled = self.swap_iq();
        let cross = scaling_imag * shuffled;
        unsafe {
            mem::transmute(_mm_addsub_ps(
                mem::transmute(parallel),
                mem::transmute(cross),
            ))
        }
    }

    #[inline]
    fn mul_complex(self, value: f32x4) -> f32x4 {
        let scaling_real = f32x4::new(
            value.extract(0),
            value.extract(0),
            value.extract(2),
            value.extract(2),
        );

        let scaling_imag = f32x4::new(
            value.extract(1),
            value.extract(1),
            value.extract(3),
            value.extract(3),
        );

        let parallel = scaling_real * self;
        let shuffled = self.swap_iq();
        let cross = scaling_imag * shuffled;
        unsafe {
            mem::transmute(_mm_addsub_ps(
                mem::transmute(parallel),
                mem::transmute(cross),
            ))
        }
    }

    #[inline]
    fn div_complex(self, value: f32x4) -> f32x4 {
        let scaling_imag = f32x4::new(
            self.extract(0),
            self.extract(0),
            self.extract(2),
            self.extract(2),
        );

        let scaling_real = f32x4::new(
            self.extract(1),
            self.extract(1),
            self.extract(3),
            self.extract(3),
        );

        let parallel = scaling_real * value;
        let shuffled = value.swap_iq();
        let cross = scaling_imag * shuffled;
        let mul: f32x4 = unsafe {
            mem::transmute(_mm_addsub_ps(
                mem::transmute(parallel),
                mem::transmute(cross),
            ))
        };
        let square = shuffled * shuffled;
        let square_shuffled = square.swap_iq();
        let sum = square + square_shuffled;
        let div = mul / sum;
        div.swap_iq()
    }

    #[inline]
    fn complex_abs_squared(self) -> f32x4 {
        let squared = self * self;
        unsafe {
            mem::transmute(_mm_hadd_ps(
                mem::transmute(squared),
                mem::transmute(squared),
            ))
        }
    }

    #[inline]
    fn complex_abs(self) -> f32x4 {
        let squared_sum = self.complex_abs_squared();
        squared_sum.sqrt()
    }

    #[inline]
    fn sqrt(self) -> f32x4 {
        self.sqrt()
    }

    #[inline]
    fn store_half_unchecked(self, target: &mut [f32], index: usize) {
        unsafe {
            *target.get_unchecked_mut(index) = self.extract(0);
            *target.get_unchecked_mut(index + 1) = self.extract(1);
        }
    }

    #[inline]
    fn sum_real(&self) -> f32 {
        self.extract(0) + self.extract(1) + self.extract(2) + self.extract(3)
    }

    #[inline]
    fn sum_complex(&self) -> Complex<f32> {
        Complex::<f32>::new(
            self.extract(0) + self.extract(2),
            self.extract(1) + self.extract(3),
        )
    }

    #[inline]
    fn max(self, other: Self) -> Self {
        self.max(other)
    }

    #[inline]
    fn min(self, other: Self) -> Self {
        self.min(other)
    }

    #[inline]
    fn swap_iq(self) -> Self {
        unsafe { mem::transmute(_mm_permute_ps(mem::transmute(self), SWAP_IQ_PS)) }
    }
}

impl Simd<f64> for f64x2 {
    type Array = [f64; 2];

    #[inline]
    fn to_array(self) -> Self::Array {
        let mut target = [0.0; 2];
        self.store(&mut target, 0);
        target
    }

    type ComplexArray = [Complex<f64>; 1];

    const LEN: usize = 2;

    #[inline]
    fn load_wrap_unchecked(array: &[f64], idx: usize) -> f64x2 {
        let mut temp = [0.0; 2];
        for (i, t) in temp.iter_mut().enumerate() {
            *t = unsafe { *array.get_unchecked((idx + i) % array.len()) };
        }

        f64x2::load(&temp, 0)
    }

    #[inline]
    fn from_complex(value: Complex<f64>) -> f64x2 {
        f64x2::new(value.re, value.im)
    }

    #[inline]
    fn add_real(self, value: f64) -> f64x2 {
        let increment = f64x2::splat(value);
        self + increment
    }

    #[inline]
    fn add_complex(self, value: Complex<f64>) -> f64x2 {
        let increment = f64x2::new(value.re, value.im);
        self + increment
    }

    #[inline]
    fn scale_real(self, value: f64) -> f64x2 {
        let scale_vector = f64x2::splat(value);
        self * scale_vector
    }

    #[inline]
    fn scale_complex(self, value: Complex<f64>) -> f64x2 {
        let complex = Complex::new(self.extract(0), self.extract(1));
        let result = complex * value;
        f64x2::new(result.re, result.im)
    }

    #[inline]
    fn mul_complex(self, value: f64x2) -> f64x2 {
        let complex = Complex::new(self.extract(0), self.extract(1));
        let value = Complex::new(value.extract(0), value.extract(1));
        let result = complex * value;
        f64x2::new(result.re, result.im)
    }

    #[inline]
    fn div_complex(self, value: f64x2) -> f64x2 {
        let complex = Complex::new(self.extract(0), self.extract(1));
        let value = Complex::new(value.extract(0), value.extract(1));
        let result = complex / value;
        f64x2::new(result.re, result.im)
    }

    #[inline]
    fn complex_abs_squared(self) -> f64x2 {
        let a = self.extract(0);
        let b = self.extract(1);
        let result = a * a + b * b;
        f64x2::new(result, 0.0)
    }

    #[inline]
    fn complex_abs(self) -> f64x2 {
        let a = self.extract(0);
        let b = self.extract(1);
        let result = (a * a + b * b).sqrt();
        f64x2::new(result, 0.0)
    }

    #[inline]
    fn sqrt(self) -> f64x2 {
        simd::x86::sse2::Sse2F64x2::sqrt(self)
    }

    #[inline]
    fn store_half_unchecked(self, target: &mut [f64], index: usize) {
        unsafe {
            *target.get_unchecked_mut(index) = self.extract(0);
        }
    }

    #[inline]
    fn sum_real(&self) -> f64 {
        self.extract(0) + self.extract(1)
    }

    #[inline]
    fn sum_complex(&self) -> Complex<f64> {
        Complex::<f64>::new(self.extract(0), self.extract(1))
    }

    #[inline]
    fn max(self, other: Self) -> Self {
        simd::x86::sse2::Sse2F64x2::max(self, other)
    }

    #[inline]
    fn min(self, other: Self) -> Self {
        simd::x86::sse2::Sse2F64x2::min(self, other)
    }

    #[inline]
    fn swap_iq(self) -> Self {
        f64x2::new(self.extract(1), self.extract(0))
    }
}

impl SimdFrom<f32x4> for i32x4 {
    fn regfrom(value: f32x4) -> Self {
        value.to_i32()
    }
}

impl SimdFrom<i32x4> for f32x4 {
    fn regfrom(value: i32x4) -> Self {
        value.to_f32()
    }
}

impl SimdFrom<f64x2> for i64x2 {
    fn regfrom(value: f64x2) -> Self {
        value.to_i64()
    }
}

impl SimdFrom<i64x2> for f64x2 {
    fn regfrom(value: i64x2) -> Self {
        value.to_f64()
    }
}

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

    #[test]
    fn shuffle_test() {
        let vec = f32x4::new(1.0, 2.0, 3.0, 4.0);
        let result = vec.swap_iq();
        assert_eq!(result.extract(0), vec.extract(1));
        assert_eq!(result.extract(1), vec.extract(0));
        assert_eq!(result.extract(2), vec.extract(3));
        assert_eq!(result.extract(3), vec.extract(2));
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
* Minimal binding for OpenAL.
* Bind only functions which are needed by lib sailor
*/

#![allow(dead_code, non_snake_case)]

#[cfg(unix)]
#[link(name = "openal")]
extern {}

#[cfg(not(unix))]
#[link(name = "openal32")]
extern {}

pub mod ffi {

    use libc::{c_char, c_void, intptr_t };

    /// OpenAL types
    pub type ALCboolean = c_char;
    pub type ALCdevicePtr = intptr_t;
    pub type ALCcontextPtr = intptr_t;
    pub const ALC_TRUE:               ALCboolean  = 1;
    pub const ALC_FALSE:              ALCboolean  = 0;

    /// Sound modifier
    pub const AL_GAIN:                i32         = 0x100A;
    pub const AL_PITCH:               i32         = 0x1003;
    pub const AL_SOURCE_RELATIVE:     i32         = 0x202;
    pub const AL_POSITION:            i32         = 0x1004;
    pub const AL_ORIENTATION:         i32         = 0x100F;
    pub const AL_DIRECTION:           i32         = 0x1005;
    pub const AL_LOOPING:             i32         = 0x1007;
    pub const AL_MIN_GAIN:            i32         = 0x100D;
    pub const AL_MAX_GAIN:            i32         = 0x100E;
    pub const AL_MAX_DISTANCE:        i32         = 0x1023;
    pub const AL_REFERENCE_DISTANCE:  i32         = 0x1020;
    pub const AL_ROLLOFF_FACTOR:      i32         = 0x1021;

    /// Sound format
    pub const AL_FORMAT_MONO16:       i32         = 0x1101;
    pub const AL_FORMAT_STEREO16:     i32         = 0x1103;
    pub const AL_FORMAT_51CHN16:      i32         = 0x120B;
    pub const AL_FORMAT_61CHN16:      i32         = 0x120E;
    pub const AL_FORMAT_71CHN16:      i32         = 0x1211;
    pub const AL_FORMAT_QUAD16:       i32         = 0x1205;

    /// Source params
    pub const AL_BUFFER:              i32         = 0x1009;
    pub const AL_BUFFERS_PROCESSED:   i32         = 0x1016;
    pub const AL_BUFFERS_QUEUED:      i32         = 0x1015;

    /// Error identifiers
    pub const AL_NO_ERROR:            i32         = 0;
    pub const AL_INVALID_NAME:        i32         = 0xA001;
    pub const AL_INVALID_ENUM:        i32         = 0xA002;
    pub const AL_INVALID_VALUE:       i32         = 0xA003;
    pub const AL_INVALID_OPERATION:   i32         = 0xA004;
    pub const AL_OUT_OF_MEMORY :      i32         = 0xA005;

    /// Source states
    pub const AL_SOURCE_STATE:        i32         = 0x1010;
    pub const AL_INITIAL:             i32         = 0x1011;
    pub const AL_PLAYING:             i32         = 0x1012;
    pub const AL_PAUSED:              i32         = 0x1013;
    pub const AL_STOPPED:             i32         = 0x1014;

    /// ALC
    pub const ALC_CAPTURE_SAMPLES :    i32         = 0x312;

    extern "C" {
        /// Context functions
        pub fn alcCreateContext(device: ALCdevicePtr, attrlist: *mut i32) -> ALCcontextPtr;
        pub fn alcMakeContextCurrent(context: ALCcontextPtr) -> ALCboolean;
        pub fn alcDestroyContext(context: ALCcontextPtr);
        pub fn alcGetCurrentContext() -> ALCcontextPtr;

        /// Device functions
        pub fn alcOpenDevice(devicename: *mut c_char) -> ALCdevicePtr;
        pub fn alcCloseDevice(device: ALCdevicePtr) -> ALCboolean;

        /// Listener functions
        pub fn alListenerf(param: i32, value: f32) -> ();
        pub fn alListener3f(param: i32, value1: f32, value2: f32, value3: f32) -> ();
        pub fn alGetListenerf(param: i32, value: *mut f32) -> ();
        pub fn alGetListener3f(param: f32, value1: *mut f32, value2: *mut f32, value3: *mut f32) -> ();
        pub fn alListenerfv(param: i32, values: *const f32) -> ();
        pub fn alGetListenerfv(param: i32, values: *mut f32) -> ();

        /// Sources functions
        pub fn alGenSources(n: i32, sources: *mut u32) -> ();
        pub fn alDeleteSources(n: i32, buffers: *mut u32) -> ();
        pub fn alSourcei(source: u32, param: i32, value: i32) -> ();
        pub fn alSourcef(source: u32, param: i32, value: f32) -> ();
        pub fn alSourcePlay(source: u32) -> ();
        pub fn alSourcePause(source: u32) -> ();
        pub fn alSourceStop(source: u32) -> ();
        pub fn alGetSourcei(source: u32, param: i32, value: *mut i32) -> ();
        pub fn alGetSourcef(source: u32, param: i32, value: *mut f32) -> ();
        pub fn alSourcefv(source: u32, param: i32, value: *const f32) -> ();
        pub fn alGetSourcefv(source: u32, param: i32, value: *mut f32) -> ();
        pub fn alSourceQueueBuffers(source: u32, nb: i32, buffers: *const u32) -> ();
        pub fn alSourceUnqueueBuffers(source: u32, nb: i32, buffers: *mut u32) -> ();

        /// Sound capture functions
        pub fn alcCaptureCloseDevice(device: ALCdevicePtr) -> ALCboolean;
        pub fn alcCaptureOpenDevice(device: *mut c_char, sample_rate: i32, format: i32, buffer_size: i32) -> ALCdevicePtr;
        pub fn alcCaptureStart(devide: ALCdevicePtr);
        pub fn alcCaptureStop(devide: ALCdevicePtr);
        pub fn alcGetIntegerv(devide: ALCdevicePtr, param: i32,  size: i32, values: *mut i32);
        pub fn alcCaptureSamples(devide: ALCdevicePtr, buffer: *mut c_void,sample: i32);

        /// extension check
        pub fn alcIsExtensionPresent(device: ALCdevicePtr, extension: *const c_char) -> ALCboolean;

        /// Buffers functions
        pub fn alGenBuffers(n: i32, buffers: *mut u32) -> ();
        pub fn alDeleteBuffers(n: i32, buffers: *mut u32);
        pub fn alBufferData(buffer: u32, format: i32, data: *mut c_void, size: i32, freq: i32) -> ();

        /// Error
        pub fn alGetError() -> i32;
    }

    #[repr(C)]
    pub struct ALCdevice;
    #[repr(C)]
    pub struct ALCcontext;
}

pub mod al {

    use super::ffi;
    use libc::c_void;

    pub fn alBufferData(buffer: u32, format: i32, data: *mut c_void, size: i32, freq: i32) -> () {
        unsafe { ffi::alBufferData(buffer, format, data, size, freq); }
    }

    pub fn alSourceQueueBuffers(source: u32, nb: i32, buffers: *const u32) -> () {
        unsafe { ffi::alSourceQueueBuffers(source, nb, buffers); }
    }

    pub fn alSourcePlay(source: u32) -> () {
        unsafe { ffi::alSourcePlay(source); }
    }

    pub fn alGetSourcei(source: u32, param: i32, value: *mut i32) -> () {
        unsafe { ffi::alGetSourcei(source, param, value); }
    }

    pub fn alGetSourcef(source: u32, param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetSourcef(source, param, value); }
    }

    pub fn alGetState(source: u32) -> i32 {
        let mut i = 0;
        unsafe { ffi::alGetSourcei(source, ffi::AL_SOURCE_STATE, &mut i); }
        i
    }

    pub fn alSourcei(source: u32, param: i32, value: i32) -> () {
        unsafe { ffi::alSourcei(source, param, value); }
    }

    pub fn alSourcef(source: u32, param: i32, value: f32) -> () {
        unsafe { ffi::alSourcef(source, param, value); }
    }

    pub fn alSourcePause(source: u32) -> () {
        unsafe { ffi::alSourcePause(source); }
    }

    pub fn alSourceStop(source: u32) -> () {
        unsafe { ffi::alSourceStop(source); }
    }

    pub fn alSourceUnqueueBuffers(source: u32, nb: i32, buffers: *mut u32) -> () {
        unsafe { ffi::alSourceUnqueueBuffers(source, nb, buffers); }
    }

    pub fn alGenSources(n: i32, sources: *mut u32) -> () {
        unsafe {ffi::alGenSources(n, sources); }
    }

    pub fn alSourcefv(source: u32, param: i32, value: *const f32) -> () {
        unsafe { ffi::alSourcefv(source, param, value); }
    }

    pub fn alGetSourcefv(source: u32, param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetSourcefv(source, param, value); }
    }

    pub fn alGenBuffers(n: i32, buffers: *mut u32) -> () {
        unsafe { ffi::alGenBuffers(n, buffers); }
    }

    pub fn alListenerf(param: i32, value: f32) -> () {
        unsafe { ffi::alListenerf(param, value); }
    }

    pub fn alListener3f(param: i32, value1: f32, value2: f32, value3: f32) -> () {
        unsafe { ffi::alListener3f(param, value1, value2, value3); }
    }

    pub fn alGetListenerf(param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetListenerf(param, value); }
    }

    pub fn alGetListener3f(param: f32, value1: *mut f32, value2: *mut f32, value3: *mut f32) -> () {
        unsafe { ffi::alGetListener3f(param, value1, value2, value3); }
    }

    pub fn alListenerfv(param: i32, values: *const f32) -> () {
        unsafe { ffi::alListenerfv(param, values); }
    }

    pub fn alGetListenerfv(param: i32, values: *mut f32) -> () {
        unsafe { ffi::alGetListenerfv(param, values); }
    }

    pub fn openal_has_error() -> Option<String> {
         match unsafe { ffi::alGetError() } {
            ffi::AL_NO_ERROR          => None,
            ffi::AL_INVALID_NAME      => Some("OpenAL error : Invalid name paramater passed to AL call.".to_string()),
            ffi::AL_INVALID_ENUM      => Some("OpenAL error : Invalid enum parameter passed to AL call.".to_string()),
            ffi::AL_INVALID_VALUE     => Some("OpenAL error : Invalid value parameter passed to AL call.".to_string()),
            ffi::AL_INVALID_OPERATION => Some("OpenAL error : Illegal AL call.".to_string()),
            ffi::AL_OUT_OF_MEMORY     => Some("OpenAL error : Not enough memory.".to_string()),
            _                         => Some("OpenAL internal error : Unknow error.".to_string())
        }
    }

    pub fn get_channels_format(channels : i32) -> Option<i32> {
        match channels {
            1 => Some(ffi::AL_FORMAT_MONO16),
            2 => Some(ffi::AL_FORMAT_STEREO16),
            4 => Some(ffi::AL_FORMAT_QUAD16),
            5 => Some(ffi::AL_FORMAT_51CHN16),
            6 => Some(ffi::AL_FORMAT_61CHN16),
            7 => Some(ffi::AL_FORMAT_71CHN16),
            _ => return None
        }
    }
}
<commit_msg>Adopt to MSYS2's new lib name for OpenAL. Fixes #2<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
* Minimal binding for OpenAL.
* Bind only functions which are needed by lib sailor
*/

#![allow(dead_code, non_snake_case)]

#[link(name = "openal")]
extern {}

pub mod ffi {

    use libc::{c_char, c_void, intptr_t };

    /// OpenAL types
    pub type ALCboolean = c_char;
    pub type ALCdevicePtr = intptr_t;
    pub type ALCcontextPtr = intptr_t;
    pub const ALC_TRUE:               ALCboolean  = 1;
    pub const ALC_FALSE:              ALCboolean  = 0;

    /// Sound modifier
    pub const AL_GAIN:                i32         = 0x100A;
    pub const AL_PITCH:               i32         = 0x1003;
    pub const AL_SOURCE_RELATIVE:     i32         = 0x202;
    pub const AL_POSITION:            i32         = 0x1004;
    pub const AL_ORIENTATION:         i32         = 0x100F;
    pub const AL_DIRECTION:           i32         = 0x1005;
    pub const AL_LOOPING:             i32         = 0x1007;
    pub const AL_MIN_GAIN:            i32         = 0x100D;
    pub const AL_MAX_GAIN:            i32         = 0x100E;
    pub const AL_MAX_DISTANCE:        i32         = 0x1023;
    pub const AL_REFERENCE_DISTANCE:  i32         = 0x1020;
    pub const AL_ROLLOFF_FACTOR:      i32         = 0x1021;

    /// Sound format
    pub const AL_FORMAT_MONO16:       i32         = 0x1101;
    pub const AL_FORMAT_STEREO16:     i32         = 0x1103;
    pub const AL_FORMAT_51CHN16:      i32         = 0x120B;
    pub const AL_FORMAT_61CHN16:      i32         = 0x120E;
    pub const AL_FORMAT_71CHN16:      i32         = 0x1211;
    pub const AL_FORMAT_QUAD16:       i32         = 0x1205;

    /// Source params
    pub const AL_BUFFER:              i32         = 0x1009;
    pub const AL_BUFFERS_PROCESSED:   i32         = 0x1016;
    pub const AL_BUFFERS_QUEUED:      i32         = 0x1015;

    /// Error identifiers
    pub const AL_NO_ERROR:            i32         = 0;
    pub const AL_INVALID_NAME:        i32         = 0xA001;
    pub const AL_INVALID_ENUM:        i32         = 0xA002;
    pub const AL_INVALID_VALUE:       i32         = 0xA003;
    pub const AL_INVALID_OPERATION:   i32         = 0xA004;
    pub const AL_OUT_OF_MEMORY :      i32         = 0xA005;

    /// Source states
    pub const AL_SOURCE_STATE:        i32         = 0x1010;
    pub const AL_INITIAL:             i32         = 0x1011;
    pub const AL_PLAYING:             i32         = 0x1012;
    pub const AL_PAUSED:              i32         = 0x1013;
    pub const AL_STOPPED:             i32         = 0x1014;

    /// ALC
    pub const ALC_CAPTURE_SAMPLES :    i32         = 0x312;

    extern "C" {
        /// Context functions
        pub fn alcCreateContext(device: ALCdevicePtr, attrlist: *mut i32) -> ALCcontextPtr;
        pub fn alcMakeContextCurrent(context: ALCcontextPtr) -> ALCboolean;
        pub fn alcDestroyContext(context: ALCcontextPtr);
        pub fn alcGetCurrentContext() -> ALCcontextPtr;

        /// Device functions
        pub fn alcOpenDevice(devicename: *mut c_char) -> ALCdevicePtr;
        pub fn alcCloseDevice(device: ALCdevicePtr) -> ALCboolean;

        /// Listener functions
        pub fn alListenerf(param: i32, value: f32) -> ();
        pub fn alListener3f(param: i32, value1: f32, value2: f32, value3: f32) -> ();
        pub fn alGetListenerf(param: i32, value: *mut f32) -> ();
        pub fn alGetListener3f(param: f32, value1: *mut f32, value2: *mut f32, value3: *mut f32) -> ();
        pub fn alListenerfv(param: i32, values: *const f32) -> ();
        pub fn alGetListenerfv(param: i32, values: *mut f32) -> ();

        /// Sources functions
        pub fn alGenSources(n: i32, sources: *mut u32) -> ();
        pub fn alDeleteSources(n: i32, buffers: *mut u32) -> ();
        pub fn alSourcei(source: u32, param: i32, value: i32) -> ();
        pub fn alSourcef(source: u32, param: i32, value: f32) -> ();
        pub fn alSourcePlay(source: u32) -> ();
        pub fn alSourcePause(source: u32) -> ();
        pub fn alSourceStop(source: u32) -> ();
        pub fn alGetSourcei(source: u32, param: i32, value: *mut i32) -> ();
        pub fn alGetSourcef(source: u32, param: i32, value: *mut f32) -> ();
        pub fn alSourcefv(source: u32, param: i32, value: *const f32) -> ();
        pub fn alGetSourcefv(source: u32, param: i32, value: *mut f32) -> ();
        pub fn alSourceQueueBuffers(source: u32, nb: i32, buffers: *const u32) -> ();
        pub fn alSourceUnqueueBuffers(source: u32, nb: i32, buffers: *mut u32) -> ();

        /// Sound capture functions
        pub fn alcCaptureCloseDevice(device: ALCdevicePtr) -> ALCboolean;
        pub fn alcCaptureOpenDevice(device: *mut c_char, sample_rate: i32, format: i32, buffer_size: i32) -> ALCdevicePtr;
        pub fn alcCaptureStart(devide: ALCdevicePtr);
        pub fn alcCaptureStop(devide: ALCdevicePtr);
        pub fn alcGetIntegerv(devide: ALCdevicePtr, param: i32,  size: i32, values: *mut i32);
        pub fn alcCaptureSamples(devide: ALCdevicePtr, buffer: *mut c_void,sample: i32);

        /// extension check
        pub fn alcIsExtensionPresent(device: ALCdevicePtr, extension: *const c_char) -> ALCboolean;

        /// Buffers functions
        pub fn alGenBuffers(n: i32, buffers: *mut u32) -> ();
        pub fn alDeleteBuffers(n: i32, buffers: *mut u32);
        pub fn alBufferData(buffer: u32, format: i32, data: *mut c_void, size: i32, freq: i32) -> ();

        /// Error
        pub fn alGetError() -> i32;
    }

    #[repr(C)]
    pub struct ALCdevice;
    #[repr(C)]
    pub struct ALCcontext;
}

pub mod al {

    use super::ffi;
    use libc::c_void;

    pub fn alBufferData(buffer: u32, format: i32, data: *mut c_void, size: i32, freq: i32) -> () {
        unsafe { ffi::alBufferData(buffer, format, data, size, freq); }
    }

    pub fn alSourceQueueBuffers(source: u32, nb: i32, buffers: *const u32) -> () {
        unsafe { ffi::alSourceQueueBuffers(source, nb, buffers); }
    }

    pub fn alSourcePlay(source: u32) -> () {
        unsafe { ffi::alSourcePlay(source); }
    }

    pub fn alGetSourcei(source: u32, param: i32, value: *mut i32) -> () {
        unsafe { ffi::alGetSourcei(source, param, value); }
    }

    pub fn alGetSourcef(source: u32, param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetSourcef(source, param, value); }
    }

    pub fn alGetState(source: u32) -> i32 {
        let mut i = 0;
        unsafe { ffi::alGetSourcei(source, ffi::AL_SOURCE_STATE, &mut i); }
        i
    }

    pub fn alSourcei(source: u32, param: i32, value: i32) -> () {
        unsafe { ffi::alSourcei(source, param, value); }
    }

    pub fn alSourcef(source: u32, param: i32, value: f32) -> () {
        unsafe { ffi::alSourcef(source, param, value); }
    }

    pub fn alSourcePause(source: u32) -> () {
        unsafe { ffi::alSourcePause(source); }
    }

    pub fn alSourceStop(source: u32) -> () {
        unsafe { ffi::alSourceStop(source); }
    }

    pub fn alSourceUnqueueBuffers(source: u32, nb: i32, buffers: *mut u32) -> () {
        unsafe { ffi::alSourceUnqueueBuffers(source, nb, buffers); }
    }

    pub fn alGenSources(n: i32, sources: *mut u32) -> () {
        unsafe {ffi::alGenSources(n, sources); }
    }

    pub fn alSourcefv(source: u32, param: i32, value: *const f32) -> () {
        unsafe { ffi::alSourcefv(source, param, value); }
    }

    pub fn alGetSourcefv(source: u32, param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetSourcefv(source, param, value); }
    }

    pub fn alGenBuffers(n: i32, buffers: *mut u32) -> () {
        unsafe { ffi::alGenBuffers(n, buffers); }
    }

    pub fn alListenerf(param: i32, value: f32) -> () {
        unsafe { ffi::alListenerf(param, value); }
    }

    pub fn alListener3f(param: i32, value1: f32, value2: f32, value3: f32) -> () {
        unsafe { ffi::alListener3f(param, value1, value2, value3); }
    }

    pub fn alGetListenerf(param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetListenerf(param, value); }
    }

    pub fn alGetListener3f(param: f32, value1: *mut f32, value2: *mut f32, value3: *mut f32) -> () {
        unsafe { ffi::alGetListener3f(param, value1, value2, value3); }
    }

    pub fn alListenerfv(param: i32, values: *const f32) -> () {
        unsafe { ffi::alListenerfv(param, values); }
    }

    pub fn alGetListenerfv(param: i32, values: *mut f32) -> () {
        unsafe { ffi::alGetListenerfv(param, values); }
    }

    pub fn openal_has_error() -> Option<String> {
         match unsafe { ffi::alGetError() } {
            ffi::AL_NO_ERROR          => None,
            ffi::AL_INVALID_NAME      => Some("OpenAL error : Invalid name paramater passed to AL call.".to_string()),
            ffi::AL_INVALID_ENUM      => Some("OpenAL error : Invalid enum parameter passed to AL call.".to_string()),
            ffi::AL_INVALID_VALUE     => Some("OpenAL error : Invalid value parameter passed to AL call.".to_string()),
            ffi::AL_INVALID_OPERATION => Some("OpenAL error : Illegal AL call.".to_string()),
            ffi::AL_OUT_OF_MEMORY     => Some("OpenAL error : Not enough memory.".to_string()),
            _                         => Some("OpenAL internal error : Unknow error.".to_string())
        }
    }

    pub fn get_channels_format(channels : i32) -> Option<i32> {
        match channels {
            1 => Some(ffi::AL_FORMAT_MONO16),
            2 => Some(ffi::AL_FORMAT_STEREO16),
            4 => Some(ffi::AL_FORMAT_QUAD16),
            5 => Some(ffi::AL_FORMAT_51CHN16),
            6 => Some(ffi::AL_FORMAT_61CHN16),
            7 => Some(ffi::AL_FORMAT_71CHN16),
            _ => return None
        }
    }
}
<|endoftext|>


<commit_before>use tokenizer::Tokenizer;
use event::{Event, Rule};
use std::collections::HashMap;

fn substitute_variables<'a>(value: &'a str, substitutions: &'a HashMap<String, String>) -> String {
    value.split(' ').map(|value_part|
        match substitutions.get(value_part) {
            Some(v) => &v[..],
            None => value_part,
        }
    ).collect::<Vec<_>>().connect(" ")
}

pub fn nested(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables: HashMap<String, String> = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => format!("{} ", name),
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!("{{\n  {}: {};", name, real_value),
                    _ => format!("\n  {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!(" }}\n"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn compressed(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!("{{{}:{}", name, real_value),
                    Event::Property(_, _) => format!(";{}:{}", name, real_value),
                    _ => format!("{}:{}", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!("}}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn expanded(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    Event::End(_) => format!("\n{}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!(" {{\n  {}: {};", name, real_value),
                    _ => format!("\n  {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!("\n}}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn compact(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    Event::End(_) => format!("\n{}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!(" {{ {}: {};", name, real_value),
                    _ => format!(" {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!(" }}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn debug(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::from_str("");
    let mut current = String::from_str("");

    while let Some(token) = tokenizer.next() {
        current.push_str(&format!("{:?}\n", token)[..]);
        match token {
            Event::End(_) => {
                output.push_str(&current[..]);
                current = String::from_str("");
            },
            _ => {},
        }
    }
    output
}
<commit_msg>Reorganize to only commit to a string at an end event<commit_after>use tokenizer::Tokenizer;
use event::{Event, Rule};
use std::collections::HashMap;

fn substitute_variables<'a>(value: &'a str, substitutions: &'a HashMap<String, String>) -> String {
    value.split(' ').map(|value_part|
        match substitutions.get(value_part) {
            Some(v) => &v[..],
            None => value_part,
        }
    ).collect::<Vec<_>>().connect(" ")
}

pub fn nested(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables: HashMap<String, String> = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => format!("{} ", name),
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!("{{\n  {}: {};", name, real_value),
                    _ => format!("\n  {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!(" }}\n"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn compressed(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!("{{{}:{}", name, real_value),
                    Event::Property(_, _) => format!(";{}:{}", name, real_value),
                    _ => format!("{}:{}", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!("}}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn expanded(tokenizer: &mut Tokenizer) -> String {
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();
    let mut output = String::from_str("");
    let mut current = String::from_str("");

    while let Some(token) = tokenizer.next() {
        match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => current.push_str(&format!(" {}", name)[..]),
                    Event::End(_) => current.push_str(&format!("\n{}", name)[..]),
                    _ => current.push_str(&format!("{}", name)[..]),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => current.push_str(&format!(" {{\n  {}: {};", name, real_value)[..]),
                    _ => current.push_str(&format!("\n  {}: {};", name, real_value)[..]),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => current.push_str(&format!("\n}}")[..]),
                };
                output.push_str(&current[..]);
                current = String::from_str("");
            },
        };

        last = token;
    }
    output
}

pub fn compact(tokenizer: &mut Tokenizer) -> String {
    let mut output =  String::from_str("");
    let mut last = Event::End(Rule::SassRule);
    let mut variables = HashMap::new();

    while let Some(token) = tokenizer.next() {
        let print_token = match token.clone() {
            Event::Start(_) => continue,
            Event::Variable(name, value) => {
                let val = substitute_variables(&value, &variables);
                variables.insert((*name).to_string(), val);
                continue
            },
            Event::Selector(name) => {
                match last {
                    Event::Selector(_) => format!(" {}", name),
                    Event::End(_) => format!("\n{}", name),
                    _ => format!("{}", name),
                }
            },
            Event::Property(name, value) => {
                let real_value = substitute_variables(&value, &variables);
                match last {
                    Event::Selector(_) => format!(" {{ {}: {};", name, real_value),
                    _ => format!(" {}: {};", name, real_value),
                }
            },
            Event::End(_) => {
                match last {
                    Event::End(_) => continue,
                    _ => format!(" }}"),
                }
            },
        };
        output.push_str(print_token.as_str());
        last = token;
    }
    output
}

pub fn debug(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::from_str("");
    let mut current = String::from_str("");

    while let Some(token) = tokenizer.next() {
        current.push_str(&format!("{:?}\n", token)[..]);
        match token {
            Event::End(_) => {
                output.push_str(&current[..]);
                current = String::from_str("");
            },
            _ => {},
        }
    }
    output
}
<|endoftext|>


<commit_before>//! This module contains the `Packet` and the `PacketHeader` structs which represent a packet
//! and its header.

use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};

use crate::{
    errors::*,
    TsResolution
};

use std::{
    borrow::Cow,
    io::Read,
    io::Write,
    time::Duration
};

/// Describes a pcap packet header.
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub struct PacketHeader {

    /// Timestamp in seconds
    pub ts_sec: u32,

    /// Nanosecond part of the timestamp
    pub ts_nsec: u32,

    /// Number of octets of the packet saved in file
    pub incl_len: u32,

    /// Original length of the packet on the wire
    pub orig_len: u32
}

impl PacketHeader {

    /// Create a new `PacketHeader` with the given parameters.
    pub fn new(ts_sec: u32, ts_nsec: u32, incl_len:u32, orig_len:u32) -> PacketHeader {

        PacketHeader {
            ts_sec,
            ts_nsec,
            incl_len,
            orig_len
        }
    }

    /// Create a new `PacketHeader` from a reader.
    pub fn from_reader<R: Read, B: ByteOrder>(reader: &mut R, ts_resolution: TsResolution) -> ResultParsing<PacketHeader> {

        let ts_sec = reader.read_u32::<B>()?;
        let mut ts_nsec = reader.read_u32::<B>()?;
        if ts_resolution == TsResolution::MicroSecond {
            ts_nsec *= 1000;
        }
        let incl_len = reader.read_u32::<B>()?;
        let orig_len = reader.read_u32::<B>()?;

        if incl_len > 0xFFFF {
            return Err(PcapError::InvalidField("PacketHeader incl_len > 0xFFFF"));
        }

        if orig_len > 0xFFFF {
            return Err(PcapError::InvalidField("PacketHeader orig_len > 0xFFFF"));
        }

        if incl_len > orig_len {
            return Err(PcapError::InvalidField("PacketHeader incl_len > orig_len"));
        }

        Ok(
            PacketHeader {

                ts_sec,
                ts_nsec,
                incl_len,
                orig_len
            }
        )
    }

    /// Create a new `PacketHeader` from a slice.
    pub fn from_slice<B: ByteOrder>(slice: &[u8], ts_resolution: TsResolution) -> ResultParsing<(PacketHeader, &[u8])> {

        let mut slice = slice;

        //Header len
        if slice.len() < 16 {
            return Err(PcapError::IncompleteBuffer(16 - slice.len()));
        }

        let header = Self::from_reader::<_, B>(&mut slice, ts_resolution)?;

        Ok((header, slice))
    }

    /// Write a `PcapHeader` to a writer.
    ///
    /// Writes 24B in the writer on success.
    pub fn write_to< W: Write, B: ByteOrder>(&self, writer: &mut W, ts_resolution: TsResolution) -> ResultParsing<()> {

        let mut ts_unsec = self.ts_nsec;
        if ts_resolution == TsResolution::MicroSecond{
            ts_unsec /= 1000;
        }
        writer.write_u32::<B>(self.ts_sec)?;
        writer.write_u32::<B>(ts_unsec)?;
        writer.write_u32::<B>(self.incl_len)?;
        writer.write_u32::<B>(self.orig_len)?;

        Ok(())
    }

    /// Get the timestamp of the packet as a Duration
    pub fn timestamp(&self) -> Duration {
        Duration::new(self.ts_sec.into(), self.ts_nsec)
    }
}

/// Packet with its header and data.
///
/// The payload can be owned or borrowed.
#[derive(Clone, Debug)]
pub struct Packet<'a> {

    /// Header of the packet
    pub header: PacketHeader,

    /// Payload, owned or borrowed, of the packet
    pub data: Cow<'a, [u8]>
}

impl<'a> Packet<'a> {

    /// Create a new borrowed `Packet` with the given parameters.
    pub fn new(ts_sec: u32, ts_nsec: u32, data: &'a [u8], orig_len: u32) -> Packet<'a> {

        let header = PacketHeader {
            ts_sec,
            ts_nsec,
            incl_len: data.len() as u32,
            orig_len
        };

        Packet {
            header,
            data: Cow::Borrowed(data)
        }
    }

    /// Create a new owned `Packet` with the given parameters.
    pub fn new_owned(ts_sec: u32, ts_nsec: u32, data: Vec<u8>, orig_len: u32) -> Packet<'static> {

        let header = PacketHeader {
            ts_sec,
            ts_nsec,
            incl_len: data.len() as u32,
            orig_len
        };

        Packet {
            header,
            data: Cow::Owned(data)
        }
    }

    /// Create a new owned `Packet` from a reader.
    pub fn from_reader<R: Read, B: ByteOrder>(reader: &mut R, ts_resolution: TsResolution) -> ResultParsing<Packet<'static>> {

        let header = PacketHeader::from_reader::<R, B>(reader, ts_resolution)?;

        let mut bytes = vec![0_u8; header.incl_len as usize];
        reader.read_exact(&mut bytes)?;

        Ok(
            Packet {

                header,
                data : Cow::Owned(bytes)
            }
        )
    }

    /// Create a new borrowed `Packet` from a slice.
    pub fn from_slice<B: ByteOrder>(slice: &'a[u8], ts_resolution: TsResolution) -> ResultParsing<(Packet<'a>, &'a[u8])> {

        let (header, slice) = PacketHeader::from_slice::<B>(slice, ts_resolution)?;
        let len = header.incl_len as usize;

        if slice.len() < len {
            return Err(PcapError::IncompleteBuffer(len - slice.len()));
        }

        let packet = Packet {
            header,
            data : Cow::Borrowed(&slice[..len])
        };

        let slice = &slice[len..];

        Ok((packet, slice))
    }

    /// Convert a borrowed `Packet` to an owned one.
    pub fn into_owned(self) -> Packet<'static> {
        Packet {
            header: self.header,
            data: Cow::Owned(self.data.into_owned())
        }
    }
}
<commit_msg>Change Packet::into_owned to Packet::to_owned<commit_after>//! This module contains the `Packet` and the `PacketHeader` structs which represent a packet
//! and its header.

use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};

use crate::{
    errors::*,
    TsResolution
};

use std::{
    borrow::Cow,
    io::Read,
    io::Write,
    time::Duration
};

/// Describes a pcap packet header.
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub struct PacketHeader {

    /// Timestamp in seconds
    pub ts_sec: u32,

    /// Nanosecond part of the timestamp
    pub ts_nsec: u32,

    /// Number of octets of the packet saved in file
    pub incl_len: u32,

    /// Original length of the packet on the wire
    pub orig_len: u32
}

impl PacketHeader {

    /// Create a new `PacketHeader` with the given parameters.
    pub fn new(ts_sec: u32, ts_nsec: u32, incl_len:u32, orig_len:u32) -> PacketHeader {

        PacketHeader {
            ts_sec,
            ts_nsec,
            incl_len,
            orig_len
        }
    }

    /// Create a new `PacketHeader` from a reader.
    pub fn from_reader<R: Read, B: ByteOrder>(reader: &mut R, ts_resolution: TsResolution) -> ResultParsing<PacketHeader> {

        let ts_sec = reader.read_u32::<B>()?;
        let mut ts_nsec = reader.read_u32::<B>()?;
        if ts_resolution == TsResolution::MicroSecond {
            ts_nsec *= 1000;
        }
        let incl_len = reader.read_u32::<B>()?;
        let orig_len = reader.read_u32::<B>()?;

        if incl_len > 0xFFFF {
            return Err(PcapError::InvalidField("PacketHeader incl_len > 0xFFFF"));
        }

        if orig_len > 0xFFFF {
            return Err(PcapError::InvalidField("PacketHeader orig_len > 0xFFFF"));
        }

        if incl_len > orig_len {
            return Err(PcapError::InvalidField("PacketHeader incl_len > orig_len"));
        }

        Ok(
            PacketHeader {

                ts_sec,
                ts_nsec,
                incl_len,
                orig_len
            }
        )
    }

    /// Create a new `PacketHeader` from a slice.
    pub fn from_slice<B: ByteOrder>(slice: &[u8], ts_resolution: TsResolution) -> ResultParsing<(PacketHeader, &[u8])> {

        let mut slice = slice;

        //Header len
        if slice.len() < 16 {
            return Err(PcapError::IncompleteBuffer(16 - slice.len()));
        }

        let header = Self::from_reader::<_, B>(&mut slice, ts_resolution)?;

        Ok((header, slice))
    }

    /// Write a `PcapHeader` to a writer.
    ///
    /// Writes 24B in the writer on success.
    pub fn write_to< W: Write, B: ByteOrder>(&self, writer: &mut W, ts_resolution: TsResolution) -> ResultParsing<()> {

        let mut ts_unsec = self.ts_nsec;
        if ts_resolution == TsResolution::MicroSecond{
            ts_unsec /= 1000;
        }
        writer.write_u32::<B>(self.ts_sec)?;
        writer.write_u32::<B>(ts_unsec)?;
        writer.write_u32::<B>(self.incl_len)?;
        writer.write_u32::<B>(self.orig_len)?;

        Ok(())
    }

    /// Get the timestamp of the packet as a Duration
    pub fn timestamp(&self) -> Duration {
        Duration::new(self.ts_sec.into(), self.ts_nsec)
    }
}

/// Packet with its header and data.
///
/// The payload can be owned or borrowed.
#[derive(Clone, Debug)]
pub struct Packet<'a> {

    /// Header of the packet
    pub header: PacketHeader,

    /// Payload, owned or borrowed, of the packet
    pub data: Cow<'a, [u8]>
}

impl<'a> Packet<'a> {

    /// Create a new borrowed `Packet` with the given parameters.
    pub fn new(ts_sec: u32, ts_nsec: u32, data: &'a [u8], orig_len: u32) -> Packet<'a> {

        let header = PacketHeader {
            ts_sec,
            ts_nsec,
            incl_len: data.len() as u32,
            orig_len
        };

        Packet {
            header,
            data: Cow::Borrowed(data)
        }
    }

    /// Create a new owned `Packet` with the given parameters.
    pub fn new_owned(ts_sec: u32, ts_nsec: u32, data: Vec<u8>, orig_len: u32) -> Packet<'static> {

        let header = PacketHeader {
            ts_sec,
            ts_nsec,
            incl_len: data.len() as u32,
            orig_len
        };

        Packet {
            header,
            data: Cow::Owned(data)
        }
    }

    /// Create a new owned `Packet` from a reader.
    pub fn from_reader<R: Read, B: ByteOrder>(reader: &mut R, ts_resolution: TsResolution) -> ResultParsing<Packet<'static>> {

        let header = PacketHeader::from_reader::<R, B>(reader, ts_resolution)?;

        let mut bytes = vec![0_u8; header.incl_len as usize];
        reader.read_exact(&mut bytes)?;

        Ok(
            Packet {

                header,
                data : Cow::Owned(bytes)
            }
        )
    }

    /// Create a new borrowed `Packet` from a slice.
    pub fn from_slice<B: ByteOrder>(slice: &'a[u8], ts_resolution: TsResolution) -> ResultParsing<(Packet<'a>, &'a[u8])> {

        let (header, slice) = PacketHeader::from_slice::<B>(slice, ts_resolution)?;
        let len = header.incl_len as usize;

        if slice.len() < len {
            return Err(PcapError::IncompleteBuffer(len - slice.len()));
        }

        let packet = Packet {
            header,
            data : Cow::Borrowed(&slice[..len])
        };

        let slice = &slice[len..];

        Ok((packet, slice))
    }

    /// Convert a borrowed `Packet` to an owned one.
    pub fn to_owned(&self) -> Packet<'static> {
        Packet {
            header: self.header,
            data: Cow::Owned(self.data.as_ref().to_owned())
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashMap};
use std::iter::{Peekable};
use std::str;
use ast;

#[derive(Debug, Eq, PartialEq)]
enum Token {
    OpenBrace,
    CloseBrace,
    OpenParen,
    CloseParen,
    OpenBracket,
    CloseBracket,
    SingleQuote,
    DoubleQuote,
    Dot,
    Plus,
    Asterik,
    Question,
    Exclamation,
    Ambersand,
    Slash,
    Name(i32),
    Letter(u8)
}

fn tokenize(grammar : &String) -> (Vec<Token>, HashMap<String, i32>) {
    let mut iterator = grammar.chars();
    let mut tokens = vec![];
    let mut name = vec![];
    let mut i = 1;
    let mut in_quote = false;
    let mut escaped = false;
    let mut map = HashMap::new();
    map.insert("main".to_string(), 0);

    while let Some(item) = iterator.next() {
        if in_quote {
            if escaped {
                tokens.push(Token::Letter(item as u8));
                escaped = false;
            } else {
                match item {
                    '\'' => {
                        tokens.push(Token::SingleQuote);
                        in_quote = false;
                    },
                    '\"' => {
                        tokens.push(Token::DoubleQuote);
                        in_quote = false;
                    },
                    '\\' => { escaped = true; },
                    _ => tokens.push(Token::Letter(item as u8))
                }
            }
        } else {
            match item {
                '{' => tokens.push(Token::OpenBrace),
                '}' => tokens.push(Token::CloseBrace),
                '(' => tokens.push(Token::OpenParen),
                ')' => tokens.push(Token::CloseParen),
                '[' => tokens.push(Token::OpenBracket),
                ']' => tokens.push(Token::CloseBracket),
                '.' => tokens.push(Token::Dot),
                '+' => tokens.push(Token::Plus),
                '*' => tokens.push(Token::Asterik),
                '?' => tokens.push(Token::Question),
                '!' => tokens.push(Token::Exclamation),
                '&' => tokens.push(Token::Ambersand),
                '/' => tokens.push(Token::Slash),
                '\'' => {
                    tokens.push(Token::SingleQuote);
                    in_quote = true;
                },
                '\"' => {
                    tokens.push(Token::DoubleQuote);
                    in_quote = true;
                },
                _ if item.is_alphanumeric() => name.push(item as u8),
                _ if item.is_whitespace() && name.len() != 0 => {
                    let id = map.entry(String::from_utf8(name.clone()).unwrap()).or_insert(i);
                    tokens.push(Token::Name(*id));
                    name.clear();
                    i += 1;
                }
                _ => { }
            }
        }
    }
    (tokens, map)
}

fn parse(grammar : &String, tokens : Vec<Token>, rule_map : HashMap<String, i32>) -> Result<ast::Grammar, u8> {
    let mut iterator = tokens.iter().peekable();
    let mut grammar_object = ast::Grammar { rules: vec![], main: 0 };
    let mut insert_order = vec![];

    while let Some(token) = iterator.next() {
        if let &Token::Name(id) = token {
            if let Some(brace_token) = iterator.next() {
                if brace_token == &Token::OpenBrace {
                    let pattern = parse_pattern(grammar, &mut iterator, false);
                    match pattern {
                        Ok(p) => insert_order.push((id, p)),
                        Err(x) => return Err(x)
                    }
                } else {
                    return Err(0);
                }
            } else {
                return Err(0);
            }
        } else {
            return Err(0);
        }
    }

    insert_order.sort_by(|a, b| a.0.cmp(&b.0));
    grammar_object.rules = insert_order.drain(..).map(|x| x.1).collect();

    Ok(grammar_object)
}

fn parse_pattern<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, is_subpattern : bool) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let mut sequence = vec![];

    while let Some(token) = iterator.next() {
        let mut initial_pattern = Err(0);
        match token {
            &Token::OpenParen => { initial_pattern = initial_pattern.or(parse_pattern(grammar, iterator, true)); },
            &Token::OpenBracket => { initial_pattern = initial_pattern.or(parse_char_class(grammar, iterator)); },
            &Token::DoubleQuote => { initial_pattern = initial_pattern.or(parse_char_sequence(grammar, iterator, false)); },
            &Token::SingleQuote => { initial_pattern = initial_pattern.or(parse_char_sequence(grammar, iterator, true)); },
            &Token::Dot => { initial_pattern = initial_pattern.or(Ok(ast::Pattern::CharAny)); },
            &Token::Name(id) => { initial_pattern = initial_pattern.or(parse_variable(grammar, id)); },
            &Token::Ambersand => { initial_pattern = initial_pattern.or(parse_lookahead(grammar, iterator, true)); },
            &Token::Exclamation => { initial_pattern = initial_pattern.or(parse_lookahead(grammar, iterator, false)); },
            _ => { }
        }

        if initial_pattern.is_ok() {
            if let Some(&suffix_token) = iterator.peek() {
                match suffix_token {
                    &Token::Plus | &Token::Asterik | &Token::Question => {
                        initial_pattern = parse_suffix(grammar, iterator, initial_pattern.ok().unwrap());
                    }
                    _ => { }
                }
            }
        }

        match initial_pattern {
            Ok(p) => sequence.push(p),
            Err(x) => return Err(x)
        }

        if let Some(&test_token) = iterator.peek() {
            match test_token {
                &Token::CloseParen => if is_subpattern {
                    iterator.next();
                } else {
                    return Err(0);
                },
                &Token::CloseBrace => if !is_subpattern {
                    iterator.next();
                    break;
                } else {
                    return Err(0);
                },
                &Token::Slash => {
                    let sub_pattern = parse_choice(grammar, iterator, &mut sequence, is_subpattern);
                    match sub_pattern {
                        Ok(p) => sequence.push(p),
                        Err(x) => return Err(x)
                    }
                },
                _ => { }
            }
        }
    }

    let mut boxed_vec = vec![];
    while let Some(item) = sequence.pop() {
        boxed_vec.push(Box::new(item));
    }

    Ok(ast::Pattern::Sequence(boxed_vec))
}

fn parse_choice<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, patterns : &mut Vec<ast::Pattern>, is_subpattern : bool) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let mut boxed_vec = vec![];
    while let Some(item) = patterns.pop() {
        boxed_vec.push(Box::new(item));
    }

    iterator.next();

    let right = parse_pattern(grammar, iterator, is_subpattern);

    match right {
        Ok(p) => Ok(ast::Pattern::Choice(
            Box::new(ast::Pattern::Sequence(boxed_vec)),
            Box::new(p))),
        Err(x) => Err(x)
    }
}

fn parse_suffix<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, pattern : ast::Pattern) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    if let Some(token) = iterator.next() {
        match token {
            &Token::Asterik => Ok(ast::Pattern::ZeroOrMore(Box::new(pattern))),
            &Token::Plus => Ok(ast::Pattern::OneOrMore(Box::new(pattern))),
            &Token::Question => Ok(ast::Pattern::Optional(Box::new(pattern))),
            _ => Err(0)
        }
    } else {
        Err(0)
    }
}

fn parse_lookahead<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, lookahead : bool) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let sub_pattern = parse_pattern(grammar, iterator, false);
    match sub_pattern {
        Ok(p) => Ok(ast::Pattern::Lookahead(lookahead, Box::new(p))),
        Err(x) => Err(x)
    }
}

fn parse_char_class<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let mut tuples = vec![];

    while let Some(&token) = iterator.peek() {
        if token == &Token::CloseBracket {
            iterator.next();
            break;
        }
        let letter = parse_char_class_element(grammar, iterator);

        if let Some(&dot_token) = iterator.peek() {
            if dot_token == &Token::Dot {
                let range_letter = parse_char_class_element(grammar, iterator);
                if letter.is_ok() && range_letter.is_ok() {
                    tuples.push((letter.ok().unwrap(), Some(range_letter.ok().unwrap())));
                } else {
                    return Err(0);
                }
            }
        }

        match letter {
            Ok(x) => tuples.push((x, None)),
            Err(x) => return Err(x)
        };
    }

    Ok(ast::Pattern::CharClass(tuples))
}

fn parse_char_class_element<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>) -> Result<u8, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let first_quote = iterator.next();
    let utf8_byte = iterator.next();
    let second_quote = iterator.next();

    if first_quote.is_some() && utf8_byte.is_some() && second_quote.is_some() {
        let single_quote_check = *first_quote.unwrap() == Token::SingleQuote
            && first_quote.unwrap() == second_quote.unwrap();
        let double_quote_check = *first_quote.unwrap() == Token::DoubleQuote
            && first_quote.unwrap() == second_quote.unwrap();

        if single_quote_check || double_quote_check {
            match utf8_byte.unwrap() {
                &Token::Letter(x) => Ok(x),
                _ => Err(0)
            }
        } else {
            Err(0)
        }
    } else {
        Err(0)
    }
}

fn parse_char_sequence<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, is_single_quote : bool) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let mut characters = vec![];
    while let Some(item) = iterator.next() {
        match item {
            &Token::Letter(x) => { characters.push(x); },
            &Token::SingleQuote if is_single_quote => { break; },
            &Token::DoubleQuote if !is_single_quote => { break; },
            _ => { return Err(0); }
        }
    }
    Ok(ast::Pattern::CharSequence(characters))
}

fn parse_variable(grammar : &String, id : i32) -> Result<ast::Pattern, u8>
{
    Ok(ast::Pattern::Variable(id))
}

<commit_msg>Fix handling rule ordering failures<commit_after>use std::collections::{HashMap};
use std::iter::{Peekable};
use std::str;
use ast;

#[derive(Debug, Eq, PartialEq)]
enum Token {
    OpenBrace,
    CloseBrace,
    OpenParen,
    CloseParen,
    OpenBracket,
    CloseBracket,
    SingleQuote,
    DoubleQuote,
    Dot,
    Plus,
    Asterik,
    Question,
    Exclamation,
    Ambersand,
    Slash,
    Name(i32),
    Letter(u8)
}

fn tokenize(grammar : &String) -> (Vec<Token>, i32) {
    let mut iterator = grammar.chars();
    let mut tokens = vec![];
    let mut name = vec![];
    let mut i = 1;
    let mut in_quote = false;
    let mut escaped = false;
    let mut map = HashMap::new();
    map.insert("main".to_string(), 0);

    while let Some(item) = iterator.next() {
        if in_quote {
            if escaped {
                tokens.push(Token::Letter(item as u8));
                escaped = false;
            } else {
                match item {
                    '\'' => {
                        tokens.push(Token::SingleQuote);
                        in_quote = false;
                    },
                    '\"' => {
                        tokens.push(Token::DoubleQuote);
                        in_quote = false;
                    },
                    '\\' => { escaped = true; },
                    _ => tokens.push(Token::Letter(item as u8))
                }
            }
        } else {
            match item {
                '{' => tokens.push(Token::OpenBrace),
                '}' => tokens.push(Token::CloseBrace),
                '(' => tokens.push(Token::OpenParen),
                ')' => tokens.push(Token::CloseParen),
                '[' => tokens.push(Token::OpenBracket),
                ']' => tokens.push(Token::CloseBracket),
                '.' => tokens.push(Token::Dot),
                '+' => tokens.push(Token::Plus),
                '*' => tokens.push(Token::Asterik),
                '?' => tokens.push(Token::Question),
                '!' => tokens.push(Token::Exclamation),
                '&' => tokens.push(Token::Ambersand),
                '/' => tokens.push(Token::Slash),
                '\'' => {
                    tokens.push(Token::SingleQuote);
                    in_quote = true;
                },
                '\"' => {
                    tokens.push(Token::DoubleQuote);
                    in_quote = true;
                },
                _ if item.is_alphanumeric() => name.push(item as u8),
                _ if item.is_whitespace() && name.len() != 0 => {
                    let id = map.entry(String::from_utf8(name.clone()).unwrap()).or_insert(i);
                    tokens.push(Token::Name(*id));
                    name.clear();
                    i += 1;
                }
                _ => { }
            }
        }
    }
    (tokens, i)
}

fn parse(grammar : &String, tokens : Vec<Token>, rule_count : i32) -> Result<ast::Grammar, u8> {
    let mut iterator = tokens.iter().peekable();
    let mut grammar_object = ast::Grammar { rules: vec![], main: 0 };
    let mut insert_order = vec![];

    while let Some(token) = iterator.next() {
        if let &Token::Name(id) = token {
            if let Some(brace_token) = iterator.next() {
                if brace_token == &Token::OpenBrace {
                    let pattern = parse_pattern(grammar, &mut iterator, false);
                    match pattern {
                        Ok(p) => insert_order.push((id, p)),
                        Err(x) => return Err(x)
                    }
                } else {
                    return Err(0);
                }
            } else {
                return Err(0);
            }
        } else {
            return Err(0);
        }
    }

    insert_order.sort_by(|a, b| a.0.cmp(&b.0));

    if insert_order.iter().map(|x| x.0).eq(0..rule_count) {
        grammar_object.rules = insert_order.drain(..).map(|x| x.1).collect();
        Ok(grammar_object)
    } else {
        Err(0)
    }
}

fn parse_pattern<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, is_subpattern : bool) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let mut sequence = vec![];

    while let Some(token) = iterator.next() {
        let mut initial_pattern = Err(0);
        match token {
            &Token::OpenParen => { initial_pattern = initial_pattern.or(parse_pattern(grammar, iterator, true)); },
            &Token::OpenBracket => { initial_pattern = initial_pattern.or(parse_char_class(grammar, iterator)); },
            &Token::DoubleQuote => { initial_pattern = initial_pattern.or(parse_char_sequence(grammar, iterator, false)); },
            &Token::SingleQuote => { initial_pattern = initial_pattern.or(parse_char_sequence(grammar, iterator, true)); },
            &Token::Dot => { initial_pattern = initial_pattern.or(Ok(ast::Pattern::CharAny)); },
            &Token::Name(id) => { initial_pattern = initial_pattern.or(parse_variable(grammar, id)); },
            &Token::Ambersand => { initial_pattern = initial_pattern.or(parse_lookahead(grammar, iterator, true)); },
            &Token::Exclamation => { initial_pattern = initial_pattern.or(parse_lookahead(grammar, iterator, false)); },
            _ => { }
        }

        if initial_pattern.is_ok() {
            if let Some(&suffix_token) = iterator.peek() {
                match suffix_token {
                    &Token::Plus | &Token::Asterik | &Token::Question => {
                        initial_pattern = parse_suffix(grammar, iterator, initial_pattern.ok().unwrap());
                    }
                    _ => { }
                }
            }
        }

        match initial_pattern {
            Ok(p) => sequence.push(p),
            Err(x) => return Err(x)
        }

        if let Some(&test_token) = iterator.peek() {
            match test_token {
                &Token::CloseParen => if is_subpattern {
                    iterator.next();
                } else {
                    return Err(0);
                },
                &Token::CloseBrace => if !is_subpattern {
                    iterator.next();
                    break;
                } else {
                    return Err(0);
                },
                &Token::Slash => {
                    let sub_pattern = parse_choice(grammar, iterator, &mut sequence, is_subpattern);
                    match sub_pattern {
                        Ok(p) => sequence.push(p),
                        Err(x) => return Err(x)
                    }
                },
                _ => { }
            }
        }
    }

    let mut boxed_vec = vec![];
    while let Some(item) = sequence.pop() {
        boxed_vec.push(Box::new(item));
    }

    Ok(ast::Pattern::Sequence(boxed_vec))
}

fn parse_choice<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, patterns : &mut Vec<ast::Pattern>, is_subpattern : bool) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let mut boxed_vec = vec![];
    while let Some(item) = patterns.pop() {
        boxed_vec.push(Box::new(item));
    }

    iterator.next();

    let right = parse_pattern(grammar, iterator, is_subpattern);

    match right {
        Ok(p) => Ok(ast::Pattern::Choice(
            Box::new(ast::Pattern::Sequence(boxed_vec)),
            Box::new(p))),
        Err(x) => Err(x)
    }
}

fn parse_suffix<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, pattern : ast::Pattern) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    if let Some(token) = iterator.next() {
        match token {
            &Token::Asterik => Ok(ast::Pattern::ZeroOrMore(Box::new(pattern))),
            &Token::Plus => Ok(ast::Pattern::OneOrMore(Box::new(pattern))),
            &Token::Question => Ok(ast::Pattern::Optional(Box::new(pattern))),
            _ => Err(0)
        }
    } else {
        Err(0)
    }
}

fn parse_lookahead<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, lookahead : bool) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let sub_pattern = parse_pattern(grammar, iterator, false);
    match sub_pattern {
        Ok(p) => Ok(ast::Pattern::Lookahead(lookahead, Box::new(p))),
        Err(x) => Err(x)
    }
}

fn parse_char_class<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let mut tuples = vec![];

    while let Some(&token) = iterator.peek() {
        if token == &Token::CloseBracket {
            iterator.next();
            break;
        }
        let letter = parse_char_class_element(grammar, iterator);

        if let Some(&dot_token) = iterator.peek() {
            if dot_token == &Token::Dot {
                let range_letter = parse_char_class_element(grammar, iterator);
                if letter.is_ok() && range_letter.is_ok() {
                    tuples.push((letter.ok().unwrap(), Some(range_letter.ok().unwrap())));
                } else {
                    return Err(0);
                }
            }
        }

        match letter {
            Ok(x) => tuples.push((x, None)),
            Err(x) => return Err(x)
        };
    }

    Ok(ast::Pattern::CharClass(tuples))
}

fn parse_char_class_element<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>) -> Result<u8, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let first_quote = iterator.next();
    let utf8_byte = iterator.next();
    let second_quote = iterator.next();

    if first_quote.is_some() && utf8_byte.is_some() && second_quote.is_some() {
        let single_quote_check = *first_quote.unwrap() == Token::SingleQuote
            && first_quote.unwrap() == second_quote.unwrap();
        let double_quote_check = *first_quote.unwrap() == Token::DoubleQuote
            && first_quote.unwrap() == second_quote.unwrap();

        if single_quote_check || double_quote_check {
            match utf8_byte.unwrap() {
                &Token::Letter(x) => Ok(x),
                _ => Err(0)
            }
        } else {
            Err(0)
        }
    } else {
        Err(0)
    }
}

fn parse_char_sequence<'a, Iter>(grammar : &String, iterator : &mut Peekable<Iter>, is_single_quote : bool) -> Result<ast::Pattern, u8>
    where Iter : Iterator<Item=&'a Token>
{
    let mut characters = vec![];
    while let Some(item) = iterator.next() {
        match item {
            &Token::Letter(x) => { characters.push(x); },
            &Token::SingleQuote if is_single_quote => { break; },
            &Token::DoubleQuote if !is_single_quote => { break; },
            _ => { return Err(0); }
        }
    }
    Ok(ast::Pattern::CharSequence(characters))
}

fn parse_variable(grammar : &String, id : i32) -> Result<ast::Pattern, u8>
{
    Ok(ast::Pattern::Variable(id))
}

<|endoftext|>