<commit_before>use super::definitions::{
    DataVector,
    VecResult,
    ErrorReason,
    DataVectorDomain};
use conv_types::*;
use RealNumber;
use num::traits::Zero;
use std::ops::Mul;
use std::fmt::Display;
use super::{
    GenericDataVector,
    RealTimeVector,
    ComplexFreqVector,
    ComplexTimeVector};
use super::time_freq_impl::{
    TimeDomainOperations,
    FrequencyDomainOperations
};
use multicore_support::{Chunk, Complexity};

/// Provides a convolution operation for data vectors.
///
/// In contrast to the convolution definition this library allows for convinience to define a convolution in frequency domain which will then correctly be executed as multiplication.
pub trait Convolution<T, C> : DataVector<T>
    where T : RealNumber {
    /// Convolves `self` with the convolution function `function`.
    /// The domain in which `function` resides defines in which domain the operation
    /// is performed. For performance reasons it is advised to pass `function` in
    /// frequency domain since this will significantly speed up the calculation in most cases.
    /// # Assumptions
    /// In frequency domain the operation assumes that the vector contains a full spectrum centered at 0 Hz. If half a spectrum
    /// or a fft shifted spectrum is provided the operation will come back with invalid results.
    /// # Failures
    /// VecResult may report the following `ErrorReason` members:
    ///
    /// 1. `VectorMustBeComplex`: if `self` is in real number space but `function` is in complex number space.
    /// 2. `VectorMustBeInTimeDomain`: if `self` is in frequency domain, `function` is in time domain and the vector can't be automatically converted to frequency domain since it is in real number space.
    fn convolve(self, function: C) -> VecResult<Self>;
}

macro_rules! add_conv_impl{
    ($($data_type:ident),*) => {
        $(
            impl<'a> Convolution<$data_type, &'a RealTimeConvFunction<$data_type>> for GenericDataVector<$data_type> {
                fn convolve(self, function: &RealTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Ok(self.convolve_priv(
                            |data|data,
                            |temp|temp,
                            |x|function.calc(x)
                        ))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexTimeConvFunction<$data_type>> for GenericDataVector<$data_type> {
                fn convolve(self, function: &ComplexTimeConvFunction<$data_type>) -> VecResult<Self> {
                    assert_complex!(self);
                    let was_time = self.domain == DataVectorDomain::Time;
                    let time =
                        if was_time {
                            self
                        } else {
                            try! { self.ifft() }
                        };

                    let result = time.convolve_priv(
                            |data|Self::array_to_complex(data),
                            |temp|Self::array_to_complex_mut(temp),
                            |x|function.calc(x)
                        );

                    if was_time {
                        Ok(result)
                    } else {
                        result.fft()
                    }
                }
            }

            impl GenericDataVector<$data_type> {
                fn convolve_priv<T,C,CMut,F>(
                    mut self,
                    convert: C,
                    convert_mut: CMut,
                    fun: F) -> Self
                        where
                            C: Fn(&[$data_type]) -> &[T],
                            CMut: Fn(&mut [$data_type]) -> &mut [T],
                            F: Fn($data_type)->T,
                            T: Zero + Mul<Output=T> + Copy + Display
                {
                    {
                        let len = self.len();
                        let delta = self.delta();
                        let complex = convert(&self.data[0..len]);
                        let dest = convert_mut(&mut self.temp[0..len]);
                        let conv_len = 11; // TODO make configurable
                        let mut i = 0;
                        for num in dest {
                            let start = if i > conv_len { i - conv_len } else { 0 };
                            let end = if i + conv_len < len { i + conv_len } else { len };
                            let mut sum = T::zero();
                            let center = i as $data_type;
                            let mut j = start as $data_type - center;
                            for c in &complex[start..end] {
                                let temp =  (*c) * fun(j * delta);
                                print!("i={}, j={} => {}\n", i, j, temp);
                                sum = sum + (*c) * fun(j * delta);
                                j += 1.0;
                            }
                            (*num) = sum;
                            i += 1;
                        }
                    }
                    self.swap_data_temp()
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexFrequencyConvFunction<$data_type>> for GenericDataVector<$data_type> {
                fn convolve(self, function: &ComplexFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    assert_complex!(self);
                    let was_time = self.domain == DataVectorDomain::Time;
                    let mut freq =
                        if was_time {
                            try!{ self.fft() }
                        } else {
                            self
                        };
                    {
                        let len = freq.len();
                        let points = freq.points();
                        let complex = Self::array_to_complex_mut(&mut freq.data[0..len]);
                        Chunk::execute_with_range(
                            Complexity::Medium, &freq.multicore_settings,
                            complex, points, 1, function,
                            move |array, range, function| {
                                let max = points as $data_type / 2.0;
                                let mut j = -((points + range.start) as $data_type) / 2.0;
                                for num in array {
                                    (*num) = (*num) * function.calc(j / max);
                                    j += 1.0;
                                }
                            });
                    }

                    if was_time {
                        freq.ifft()
                    } else {
                        Ok(freq)
                    }
                }
            }

            impl<'a> Convolution<$data_type, &'a RealFrequencyConvFunction<$data_type>> for GenericDataVector<$data_type> {
                fn convolve(self, function: &RealFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    assert_complex!(self);
                    let was_time = self.domain == DataVectorDomain::Time;
                    let mut freq =
                        if was_time {
                            try!{ self.fft() }
                        } else {
                            self
                        };
                    {
                        let len = freq.len();
                        let points = freq.points();
                        let complex = Self::array_to_complex_mut(&mut freq.data[0..len]);
                        Chunk::execute_with_range(
                            Complexity::Medium, &freq.multicore_settings,
                            complex, points, 1, function,
                            move |array, range, function| {
                                let max = points as $data_type / 2.0;
                                let mut j = -((points + range.start) as $data_type) / 2.0;
                                for num in array {
                                    (*num) = (*num) * function.calc(j / max);
                                    j += 1.0;
                                }
                            });
                    }

                    if was_time {
                        freq.ifft()
                    } else {
                        Ok(freq)
                    }
                }
            }
        )*
    }
}
add_conv_impl!(f32, f64);

macro_rules! add_conv_forw{
    ($($data_type:ident),*) => {
        $(
            impl<'a> Convolution<$data_type, &'a RealTimeConvFunction<$data_type>> for RealTimeVector<$data_type> {
                fn convolve(self, function: &RealTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a RealTimeConvFunction<$data_type>> for ComplexTimeVector<$data_type> {
                fn convolve(self, function: &RealTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a RealTimeConvFunction<$data_type>> for ComplexFreqVector<$data_type> {
                fn convolve(self, function: &RealTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexTimeConvFunction<$data_type>> for ComplexTimeVector<$data_type> {
                fn convolve(self, function: &ComplexTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexFrequencyConvFunction<$data_type>> for ComplexTimeVector<$data_type> {
                fn convolve(self, function: &ComplexFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexTimeConvFunction<$data_type>> for ComplexFreqVector<$data_type> {
                fn convolve(self, function: &ComplexTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexFrequencyConvFunction<$data_type>> for ComplexFreqVector<$data_type> {
                fn convolve(self, function: &ComplexFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a RealFrequencyConvFunction<$data_type>> for ComplexTimeVector<$data_type> {
                fn convolve(self, function: &RealFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a RealFrequencyConvFunction<$data_type>> for ComplexFreqVector<$data_type> {
                fn convolve(self, function: &RealFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }
        )*
    }
}
add_conv_forw!(f32, f64);

#[cfg(test)]
mod tests {
	use super::*;
    use super::super::{
        ComplexFreqVector32,
        RealTimeVector32,
        DataVector};
    use conv_types::*;
    use RealNumber;
    use std::fmt::Debug;
    use num::complex::Complex32;

    fn assert_eq_tol<T>(left: &[T], right: &[T], tol: T)
        where T: RealNumber + Debug {
        assert_eq!(left.len(), right.len());
        for i in 0..left.len() {
            if (left[i] - right[i]).abs() > tol {
                panic!("assertion failed: {:?} != {:?}", left, right);
            }
        }
    }
    /*
	#[test]
	fn convolve_real_and_time32() {
        let result = {
            let vector = RealTimeVector32::from_constant(1.0, 10);
            let conv = RaiseCosineFuncton::new(0.35);
            vector.convolve(&conv).unwrap()
        };

        assert_eq!(result.data(), &[0.0; 10])
    }

    #[test]
	fn convolve_complex_time_and_time32() {
        let vector = ComplexTimeVector32::from_constant(Complex32::new(1.0, 0.0), 10);
        let rc = RaiseCosineFuncton::new(0.35);
        let real = RealTimeLinearTableLookup::<f32>::from_conv_function(&rc, 0.4, 10);
        let complex = real.to_complex();
        let result = vector.convolve(&complex as &ComplexTimeConvFunction<f32>).unwrap();
        assert_eq!(result.data(), &[0.0; 10])
    }

    #[test]
	fn convolve_complex_time_and_freq32() {
        let vector = ComplexTimeVector32::from_constant(Complex32::new(1.0, 0.0), 10);
        let rc = RaiseCosineFuncton::new(0.35);
        let real = RealTimeLinearTableLookup::<f32>::from_conv_function(&rc, 0.4, 10);
        let freq = real.to_complex().fft();
        let result = vector.convolve(&freq as &ComplexFrequencyConvFunction<f32>).unwrap();
        assert_eq!(result.data(), &[0.0; 10])
    }

    #[test]
	fn convolve_complex_freq_and_time32() {
        let vector = ComplexFreqVector32::from_constant(Complex32::new(1.0, 0.0), 10);
        let rc = RaiseCosineFuncton::new(0.35);
        let real = RealTimeLinearTableLookup::<f32>::from_conv_function(&rc, 0.4, 10);
        let complex = real.to_complex();
        let result = vector.convolve(&complex as &ComplexTimeConvFunction<f32>).unwrap();
        assert_eq!(result.data(), &[0.0; 10])
    }*/

    #[test]
	fn convolve_real_freq_and_freq32() {
        let vector = ComplexFreqVector32::from_constant(Complex32::new(1.0, 1.0), 10);
        let rc: RaisedCosineFuncton<f32> = RaisedCosineFuncton::new(1.0);
        let result = vector.convolve(&rc as &RealFrequencyConvFunction<f32>).unwrap();
        let expected =
            [0.0, 0.0, 0.3454914, 0.3454914, 0.9045085, 0.9045085, 0.9045085, 0.9045085, 0.3454914, 0.3454914];
        assert_eq_tol(result.data(), &expected, 1e-4);
    }

    #[test]
	fn convolve_real_time_and_time32() {
        let vector = RealTimeVector32::from_array_with_delta(&[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0], 0.2);
        let rc: RaisedCosineFuncton<f32> = RaisedCosineFuncton::new(0.35);
        let result = vector.convolve(&rc as &RealTimeConvFunction<f32>).unwrap();
        let expected =
            [0.0, 0.2171850639713355, 0.4840621929215732, 0.7430526238101408, 0.9312114164253432,
             1.0, 0.9312114164253432, 0.7430526238101408, 0.4840621929215732, 0.2171850639713355];
        assert_eq_tol(result.data(), &expected, 1e-4);
    }
}<commit_msg>Reduced ode duplication<commit_after>use super::definitions::{
    DataVector,
    VecResult,
    ErrorReason,
    DataVectorDomain};
use conv_types::*;
use RealNumber;
use num::traits::Zero;
use std::ops::Mul;
use std::fmt::Display;
use num::complex::Complex;
use super::{
    GenericDataVector,
    RealTimeVector,
    ComplexFreqVector,
    ComplexTimeVector};
use super::time_freq_impl::{
    TimeDomainOperations,
    FrequencyDomainOperations
};
use multicore_support::{Chunk, Complexity};

/// Provides a convolution operation for data vectors.
///
/// In contrast to the convolution definition this library allows for convinience to define a convolution in frequency domain which will then correctly be executed as multiplication.
pub trait Convolution<T, C> : DataVector<T>
    where T : RealNumber {
    /// Convolves `self` with the convolution function `function`.
    /// The domain in which `function` resides defines in which domain the operation
    /// is performed. For performance reasons it is advised to pass `function` in
    /// frequency domain since this will significantly speed up the calculation in most cases.
    /// # Assumptions
    /// In frequency domain the operation assumes that the vector contains a full spectrum centered at 0 Hz. If half a spectrum
    /// or a fft shifted spectrum is provided the operation will come back with invalid results.
    /// # Failures
    /// VecResult may report the following `ErrorReason` members:
    ///
    /// 1. `VectorMustBeComplex`: if `self` is in real number space but `function` is in complex number space.
    /// 2. `VectorMustBeInTimeDomain`: if `self` is in frequency domain, `function` is in time domain and the vector can't be automatically converted to frequency domain since it is in real number space.
    fn convolve(self, function: C) -> VecResult<Self>;
}

macro_rules! add_conv_impl{
    ($($data_type:ident),*) => {
        $(
            impl<'a> Convolution<$data_type, &'a RealTimeConvFunction<$data_type>> for GenericDataVector<$data_type> {
                fn convolve(self, function: &RealTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Ok(self.convolve_priv(
                            |data|data,
                            |temp|temp,
                            |x|function.calc(x)
                        ))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexTimeConvFunction<$data_type>> for GenericDataVector<$data_type> {
                fn convolve(self, function: &ComplexTimeConvFunction<$data_type>) -> VecResult<Self> {
                    assert_complex!(self);
                    let was_time = self.domain == DataVectorDomain::Time;
                    let time =
                        if was_time {
                            self
                        } else {
                            try! { self.ifft() }
                        };

                    let result = time.convolve_priv(
                            |data|Self::array_to_complex(data),
                            |temp|Self::array_to_complex_mut(temp),
                            |x|function.calc(x)
                        );

                    if was_time {
                        Ok(result)
                    } else {
                        result.fft()
                    }
                }
            }

            impl GenericDataVector<$data_type> {
                fn convolve_priv<T,C,CMut,F>(
                    mut self,
                    convert: C,
                    convert_mut: CMut,
                    fun: F) -> Self
                        where
                            C: Fn(&[$data_type]) -> &[T],
                            CMut: Fn(&mut [$data_type]) -> &mut [T],
                            F: Fn($data_type)->T,
                            T: Zero + Mul<Output=T> + Copy + Display
                {
                    {
                        let len = self.len();
                        let delta = self.delta();
                        let complex = convert(&self.data[0..len]);
                        let dest = convert_mut(&mut self.temp[0..len]);
                        let conv_len = 11; // TODO make configurable
                        let mut i = 0;
                        for num in dest {
                            let start = if i > conv_len { i - conv_len } else { 0 };
                            let end = if i + conv_len < len { i + conv_len } else { len };
                            let mut sum = T::zero();
                            let center = i as $data_type;
                            let mut j = start as $data_type - center;
                            for c in &complex[start..end] {
                                let temp =  (*c) * fun(j * delta);
                                print!("i={}, j={} => {}\n", i, j, temp);
                                sum = sum + (*c) * fun(j * delta);
                                j += 1.0;
                            }
                            (*num) = sum;
                            i += 1;
                        }
                    }
                    self.swap_data_temp()
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexFrequencyConvFunction<$data_type>> for GenericDataVector<$data_type> {
                fn convolve(self, function: &ComplexFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    assert_complex!(self);
                    let was_time = self.domain == DataVectorDomain::Time;
                    let freq =
                        if was_time {
                            try!{ self.fft() }
                        } else {
                            self
                        };

                    let result = freq.multiply_function_priv(
                                    |array|Self::array_to_complex_mut(array),
                                    function,
                                    |f,x|f.calc(x));

                    if was_time {
                        result.ifft()
                    } else {
                        Ok(result)
                    }
                }
            }

            impl<'a> Convolution<$data_type, &'a RealFrequencyConvFunction<$data_type>> for GenericDataVector<$data_type> {
                fn convolve(self, function: &RealFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    assert_complex!(self);
                    let was_time = self.domain == DataVectorDomain::Time;
                    let freq =
                        if was_time {
                            try!{ self.fft() }
                        } else {
                            self
                        };
                    let result = freq.multiply_function_priv(
                                    |array|Self::array_to_complex_mut(array),
                                    function,
                                    |f,x|Complex::<$data_type>::new(f.calc(x), 0.0));

                    if was_time {
                        result.ifft()
                    } else {
                        Ok(result)
                    }
                }
            }

            impl GenericDataVector<$data_type> {
                fn multiply_function_priv<T,CMut,FA, F>(
                    mut self,
                    convert_mut: CMut,
                    function_arg: FA,
                    fun: F) -> Self
                        where
                            CMut: Fn(&mut [$data_type]) -> &mut [T],
                            FA: Copy + Sync,
                            F: Fn(FA, $data_type)->T + 'static + Sync,
                            T: Zero + Mul<Output=T> + Copy + Display + Send + Sync
                {
                    {
                        let len = self.len();
                        let points = self.points();
                        let complex = convert_mut(&mut self.data[0..len]);
                        Chunk::execute_with_range(
                            Complexity::Medium, &self.multicore_settings,
                            complex, points, 1, function_arg,
                            move |array, range, arg| {
                                let max = points as $data_type / 2.0;
                                let mut j = -((points + range.start) as $data_type) / 2.0;
                                for num in array {
                                    (*num) = (*num) * fun(arg, j / max);
                                    j += 1.0;
                                }
                            });
                    }
                    self
                }
            }
        )*
    }
}
add_conv_impl!(f32, f64);

macro_rules! add_conv_forw{
    ($($data_type:ident),*) => {
        $(
            impl<'a> Convolution<$data_type, &'a RealTimeConvFunction<$data_type>> for RealTimeVector<$data_type> {
                fn convolve(self, function: &RealTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a RealTimeConvFunction<$data_type>> for ComplexTimeVector<$data_type> {
                fn convolve(self, function: &RealTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a RealTimeConvFunction<$data_type>> for ComplexFreqVector<$data_type> {
                fn convolve(self, function: &RealTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexTimeConvFunction<$data_type>> for ComplexTimeVector<$data_type> {
                fn convolve(self, function: &ComplexTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexFrequencyConvFunction<$data_type>> for ComplexTimeVector<$data_type> {
                fn convolve(self, function: &ComplexFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexTimeConvFunction<$data_type>> for ComplexFreqVector<$data_type> {
                fn convolve(self, function: &ComplexTimeConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a ComplexFrequencyConvFunction<$data_type>> for ComplexFreqVector<$data_type> {
                fn convolve(self, function: &ComplexFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a RealFrequencyConvFunction<$data_type>> for ComplexTimeVector<$data_type> {
                fn convolve(self, function: &RealFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }

            impl<'a> Convolution<$data_type, &'a RealFrequencyConvFunction<$data_type>> for ComplexFreqVector<$data_type> {
                fn convolve(self, function: &RealFrequencyConvFunction<$data_type>) -> VecResult<Self> {
                    Self::from_genres(self.to_gen().convolve(function))
                }
            }
        )*
    }
}
add_conv_forw!(f32, f64);

#[cfg(test)]
mod tests {
	use super::*;
    use super::super::{
        ComplexFreqVector32,
        RealTimeVector32,
        DataVector};
    use conv_types::*;
    use RealNumber;
    use std::fmt::Debug;
    use num::complex::Complex32;

    fn assert_eq_tol<T>(left: &[T], right: &[T], tol: T)
        where T: RealNumber + Debug {
        assert_eq!(left.len(), right.len());
        for i in 0..left.len() {
            if (left[i] - right[i]).abs() > tol {
                panic!("assertion failed: {:?} != {:?}", left, right);
            }
        }
    }
    /*
	#[test]
	fn convolve_real_and_time32() {
        let result = {
            let vector = RealTimeVector32::from_constant(1.0, 10);
            let conv = RaiseCosineFuncton::new(0.35);
            vector.convolve(&conv).unwrap()
        };

        assert_eq!(result.data(), &[0.0; 10])
    }

    #[test]
	fn convolve_complex_time_and_time32() {
        let vector = ComplexTimeVector32::from_constant(Complex32::new(1.0, 0.0), 10);
        let rc = RaiseCosineFuncton::new(0.35);
        let real = RealTimeLinearTableLookup::<f32>::from_conv_function(&rc, 0.4, 10);
        let complex = real.to_complex();
        let result = vector.convolve(&complex as &ComplexTimeConvFunction<f32>).unwrap();
        assert_eq!(result.data(), &[0.0; 10])
    }

    #[test]
	fn convolve_complex_time_and_freq32() {
        let vector = ComplexTimeVector32::from_constant(Complex32::new(1.0, 0.0), 10);
        let rc = RaiseCosineFuncton::new(0.35);
        let real = RealTimeLinearTableLookup::<f32>::from_conv_function(&rc, 0.4, 10);
        let freq = real.to_complex().fft();
        let result = vector.convolve(&freq as &ComplexFrequencyConvFunction<f32>).unwrap();
        assert_eq!(result.data(), &[0.0; 10])
    }

    #[test]
	fn convolve_complex_freq_and_time32() {
        let vector = ComplexFreqVector32::from_constant(Complex32::new(1.0, 0.0), 10);
        let rc = RaiseCosineFuncton::new(0.35);
        let real = RealTimeLinearTableLookup::<f32>::from_conv_function(&rc, 0.4, 10);
        let complex = real.to_complex();
        let result = vector.convolve(&complex as &ComplexTimeConvFunction<f32>).unwrap();
        assert_eq!(result.data(), &[0.0; 10])
    }*/

    #[test]
	fn convolve_real_freq_and_freq32() {
        let vector = ComplexFreqVector32::from_constant(Complex32::new(1.0, 1.0), 10);
        let rc: RaisedCosineFuncton<f32> = RaisedCosineFuncton::new(1.0);
        let result = vector.convolve(&rc as &RealFrequencyConvFunction<f32>).unwrap();
        let expected =
            [0.0, 0.0, 0.3454914, 0.3454914, 0.9045085, 0.9045085, 0.9045085, 0.9045085, 0.3454914, 0.3454914];
        assert_eq_tol(result.data(), &expected, 1e-4);
    }

    #[test]
	fn convolve_real_time_and_time32() {
        let vector = RealTimeVector32::from_array_with_delta(&[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0], 0.2);
        let rc: RaisedCosineFuncton<f32> = RaisedCosineFuncton::new(0.35);
        let result = vector.convolve(&rc as &RealTimeConvFunction<f32>).unwrap();
        let expected =
            [0.0, 0.2171850639713355, 0.4840621929215732, 0.7430526238101408, 0.9312114164253432,
             1.0, 0.9312114164253432, 0.7430526238101408, 0.4840621929215732, 0.2171850639713355];
        assert_eq_tol(result.data(), &expected, 1e-4);
    }
}<|endoftext|>


<commit_before>//! # CLI
//!
//! The command line version of the library. Given a file path argument, it will ingest all the
//! data into memory, and attempt parsing. If the parsing is successful, JSON is outputted to
//! stdout, else a non-helpful error message is printed. Sorry!
#![cfg_attr(feature = "afl-feat", feature(plugin))]
#![cfg_attr(feature = "afl-feat", plugin(afl_plugin))]
#[cfg(feature = "afl-feat")]
extern crate afl;
extern crate boxcars;
extern crate nom;
extern crate serde_json;

use std::env;
use std::fs::File;
use std::io::Read;

#[cfg(not(feature = "afl-feat"))]
fn main() {
    let mut args: Vec<_> = env::args().collect();
    let filename = args.remove(1);
    let mut f = File::open(filename).unwrap();
    let mut buffer = vec![];
    f.read_to_end(&mut buffer).unwrap();
    let b = boxcars::parse(&buffer, true);
    match b {
        Ok(val) => {
            let serialized = serde_json::to_string(&val).unwrap();
            println!("{}", serialized);
        }
        _ => {
            println!("Oh no we failed to parse");
        }
    }
}

#[cfg(feature = "afl-feat")]
fn main() {
    afl::handle_bytes(|s| {
        let _ = boxcars::parse(&s, true);
    });
}
<commit_msg>Remove intermediate json string<commit_after>//! # CLI
//!
//! The command line version of the library. Given a file path argument, it will ingest all the
//! data into memory, and attempt parsing. If the parsing is successful, JSON is outputted to
//! stdout, else a non-helpful error message is printed. Sorry!
#![cfg_attr(feature = "afl-feat", feature(plugin))]
#![cfg_attr(feature = "afl-feat", plugin(afl_plugin))]
#[cfg(feature = "afl-feat")]
extern crate afl;
extern crate boxcars;
extern crate nom;
extern crate serde_json;

use std::env;
use std::fs::File;
use std::io::{self, Read};

#[cfg(not(feature = "afl-feat"))]
fn main() {
    let mut args: Vec<_> = env::args().collect();
    let filename = args.remove(1);
    let mut f = File::open(filename).unwrap();
    let mut buffer = vec![];
    f.read_to_end(&mut buffer).unwrap();
    let b = boxcars::parse(&buffer, true);
    match b {
        Ok(val) => {
            serde_json::to_writer(&mut io::stdout(), &val).unwrap();
        }
        _ => {
            println!("Oh no we failed to parse");
        }
    }
}

#[cfg(feature = "afl-feat")]
fn main() {
    afl::handle_bytes(|s| {
        let _ = boxcars::parse(&s, true);
    });
}
<|endoftext|>


<commit_before>use std::io;
use super::{Deserialize, Serialize, Error, Uint32};
use super::section::{
    Section, CodeSection, TypeSection, ImportSection, FunctionsSection,
    GlobalSection, TableSection, ElementSection, DataSection, MemorySection,
};

/// WebAssembly module
pub struct Module {
    magic: u32,
    version: u32,
    sections: Vec<Section>,
}

impl Default for Module {
    fn default() -> Self {
        Module {
            magic: 0x6d736100,
            version: 1,
            sections: Vec::with_capacity(16),
        }
    }
}

impl Module {
    /// New module with sections
    pub fn new(sections: Vec<Section>) -> Self {
        Module {
            sections: sections, ..Default::default()
        }
    }

    /// Destructure the module, yielding sections
    pub fn into_sections(self) -> Vec<Section> {
        self.sections
    }

    /// Version of module.
    pub fn version(&self) -> u32 { self.version }

    /// Sections list.
    /// Each known section is optional and may appear at most once.
    pub fn sections(&self) -> &[Section] {
        &self.sections
    }

    /// Sections list (mutable)
    /// Each known section is optional and may appear at most once.
    pub fn sections_mut(&mut self) -> &mut Vec<Section> {
        &mut self.sections
    }

    /// Code section, if any.
    pub fn code_section(&self) -> Option<&CodeSection> {
        for section in self.sections() {
            if let &Section::Code(ref code_section) = section { return Some(code_section); }
        }
        None
    }

    /// Types section, if any.
    pub fn type_section(&self) -> Option<&TypeSection> {
        for section in self.sections() {
            if let &Section::Type(ref type_section) = section { return Some(type_section); }
        }
        None
    }

    /// Imports section, if any.
    pub fn import_section(&self) -> Option<&ImportSection> {
        for section in self.sections() {
            if let &Section::Import(ref import_section) = section { return Some(import_section); }
        }
        None
    }

    /// Globals section, if any.
    pub fn global_section(&self) -> Option<&GlobalSection> {
        for section in self.sections() {
            if let &Section::Global(ref section) = section { return Some(section); }
        }
        None
    }

    /// Table section, if any.
    pub fn table_section(&self) -> Option<&TableSection> {
        for section in self.sections() {
            if let &Section::Table(ref section) = section { return Some(section); }
        }
        None
    }

    /// Data section, if any.
    pub fn data_section(&self) -> Option<&DataSection> {
        for section in self.sections() {
            if let &Section::Data(ref section) = section { return Some(section); }
        }
        None
    }

    /// Element section, if any.
    pub fn elements_section(&self) -> Option<&ElementSection> {
        for section in self.sections() {
            if let &Section::Element(ref section) = section { return Some(section); }
        }
        None
    }

    /// Memory section, if any.
    pub fn memory_section(&self) -> Option<&MemorySection> {
        for section in self.sections() {
            if let &Section::Memory(ref section) = section { return Some(section); }
        }
        None
    }

    /// Functions signatures section, if any.
    pub fn functions_section(&self) -> Option<&FunctionsSection> {
        for section in self.sections() {
            if let &Section::Function(ref sect) = section { return Some(sect); }
        }
        None
    }
}

impl Deserialize for Module {
    type Error = super::Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut sections = Vec::new();
        let magic = Uint32::deserialize(reader)?;
        let version = Uint32::deserialize(reader)?;

        loop {
            match Section::deserialize(reader) {
                Err(Error::UnexpectedEof) => { break; },
                Err(e) => { return Err(e) },
                Ok(section) => { sections.push(section); }
            }
        }

        Ok(Module {
            magic: magic.into(),
            version: version.into(),
            sections: sections,
        })
    }
}

impl Serialize for Module {
    type Error = Error;

    fn serialize<W: io::Write>(self, w: &mut W) -> Result<(), Self::Error> {
        Uint32::from(self.magic).serialize(w)?;
        Uint32::from(self.version).serialize(w)?;
        for section in self.sections.into_iter() {
            section.serialize(w)?;
        }
        Ok(())
    }
}

#[cfg(test)]
mod integration_tests {

    use super::super::{deserialize_file, serialize, deserialize_buffer, Section};
    use super::Module;

    #[test]
    fn hello() {
        let module = deserialize_file("./res/cases/v1/hello.wasm").expect("Should be deserialized");

        assert_eq!(module.version(), 1);
        assert_eq!(module.sections().len(), 8);
    }

    #[test]
    fn serde() {
        let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        let buf = serialize(module).expect("serialization to succeed");

        let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
        let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");

        assert_eq!(module_old.sections().len(), module_new.sections().len());
    }

    #[test]
    fn serde_type() {
        let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        module.sections_mut().retain(|x| {
            if let &Section::Type(_) = x { true } else { false }
        });

        let buf = serialize(module).expect("serialization to succeed");

        let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
        let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        assert_eq!(
            module_old.type_section().expect("type section exists").types().len(),
            module_new.type_section().expect("type section exists").types().len(),
            "There should be equal amount of types before and after serialization"
        );
    }

    #[test]
    fn serde_import() {
        let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        module.sections_mut().retain(|x| {
            if let &Section::Import(_) = x { true } else { false }
        });

        let buf = serialize(module).expect("serialization to succeed");

        let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
        let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        assert_eq!(
            module_old.import_section().expect("import section exists").entries().len(),
            module_new.import_section().expect("import section exists").entries().len(),
            "There should be equal amount of import entries before and after serialization"
        );
    }

    #[test]
    fn serde_code() {
        let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        module.sections_mut().retain(|x| {
            if let &Section::Code(_) = x { true } else { false }
        });

        let buf = serialize(module).expect("serialization to succeed");

        let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
        let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        assert_eq!(
            module_old.code_section().expect("code section exists").bodies().len(),
            module_new.code_section().expect("code section exists").bodies().len(),
            "There should be equal amount of function bodies before and after serialization"
        );
    }

    #[test]
    fn const_() {
        use super::super::Opcode::*;

        let module = deserialize_file("./res/cases/v1/const.wasm").expect("Should be deserialized");
        let func = &module.code_section().expect("Code section to exist").bodies()[0];
        assert_eq!(func.code().elements().len(), 14);

        assert_eq!(I32Const(1024), func.code().elements()[0]);
        assert_eq!(I32Const(2048), func.code().elements()[1]);
        assert_eq!(I32Const(4096), func.code().elements()[2]);
        assert_eq!(I32Const(8192), func.code().elements()[3]);
        assert_eq!(I32Const(16384), func.code().elements()[4]);
        assert_eq!(I32Const(32767), func.code().elements()[5]);
        assert_eq!(I32Const(-1024), func.code().elements()[6]);
        assert_eq!(I32Const(-2048), func.code().elements()[7]);
        assert_eq!(I32Const(-4096), func.code().elements()[8]);
        assert_eq!(I32Const(-8192), func.code().elements()[9]);
        assert_eq!(I32Const(-16384), func.code().elements()[10]);
        assert_eq!(I32Const(-32768), func.code().elements()[11]);
    }
}<commit_msg>export section<commit_after>use std::io;
use super::{Deserialize, Serialize, Error, Uint32};
use super::section::{
    Section, CodeSection, TypeSection, ImportSection, FunctionsSection,
    GlobalSection, TableSection, ElementSection, DataSection, MemorySection,
    ExportSection,
};

/// WebAssembly module
pub struct Module {
    magic: u32,
    version: u32,
    sections: Vec<Section>,
}

impl Default for Module {
    fn default() -> Self {
        Module {
            magic: 0x6d736100,
            version: 1,
            sections: Vec::with_capacity(16),
        }
    }
}

impl Module {
    /// New module with sections
    pub fn new(sections: Vec<Section>) -> Self {
        Module {
            sections: sections, ..Default::default()
        }
    }

    /// Destructure the module, yielding sections
    pub fn into_sections(self) -> Vec<Section> {
        self.sections
    }

    /// Version of module.
    pub fn version(&self) -> u32 { self.version }

    /// Sections list.
    /// Each known section is optional and may appear at most once.
    pub fn sections(&self) -> &[Section] {
        &self.sections
    }

    /// Sections list (mutable)
    /// Each known section is optional and may appear at most once.
    pub fn sections_mut(&mut self) -> &mut Vec<Section> {
        &mut self.sections
    }

    /// Code section, if any.
    pub fn code_section(&self) -> Option<&CodeSection> {
        for section in self.sections() {
            if let &Section::Code(ref code_section) = section { return Some(code_section); }
        }
        None
    }

    /// Types section, if any.
    pub fn type_section(&self) -> Option<&TypeSection> {
        for section in self.sections() {
            if let &Section::Type(ref type_section) = section { return Some(type_section); }
        }
        None
    }

    /// Imports section, if any.
    pub fn import_section(&self) -> Option<&ImportSection> {
        for section in self.sections() {
            if let &Section::Import(ref import_section) = section { return Some(import_section); }
        }
        None
    }

    /// Globals section, if any.
    pub fn global_section(&self) -> Option<&GlobalSection> {
        for section in self.sections() {
            if let &Section::Global(ref section) = section { return Some(section); }
        }
        None
    }

    /// Table section, if any.
    pub fn table_section(&self) -> Option<&TableSection> {
        for section in self.sections() {
            if let &Section::Table(ref section) = section { return Some(section); }
        }
        None
    }

    /// Data section, if any.
    pub fn data_section(&self) -> Option<&DataSection> {
        for section in self.sections() {
            if let &Section::Data(ref section) = section { return Some(section); }
        }
        None
    }

    /// Element section, if any.
    pub fn elements_section(&self) -> Option<&ElementSection> {
        for section in self.sections() {
            if let &Section::Element(ref section) = section { return Some(section); }
        }
        None
    }

    /// Memory section, if any.
    pub fn memory_section(&self) -> Option<&MemorySection> {
        for section in self.sections() {
            if let &Section::Memory(ref section) = section { return Some(section); }
        }
        None
    }

    /// Functions signatures section, if any.
    pub fn functions_section(&self) -> Option<&FunctionsSection> {
        for section in self.sections() {
            if let &Section::Function(ref sect) = section { return Some(sect); }
        }
        None
    }

    /// Export section, if any.
    pub fn export_section(&self) -> Option<&ExportSection> {
        for section in self.sections() {
            if let &Section::Export(ref sect) = section { return Some(sect); }
        }
        None
    }
}

impl Deserialize for Module {
    type Error = super::Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut sections = Vec::new();
        let magic = Uint32::deserialize(reader)?;
        let version = Uint32::deserialize(reader)?;

        loop {
            match Section::deserialize(reader) {
                Err(Error::UnexpectedEof) => { break; },
                Err(e) => { return Err(e) },
                Ok(section) => { sections.push(section); }
            }
        }

        Ok(Module {
            magic: magic.into(),
            version: version.into(),
            sections: sections,
        })
    }
}

impl Serialize for Module {
    type Error = Error;

    fn serialize<W: io::Write>(self, w: &mut W) -> Result<(), Self::Error> {
        Uint32::from(self.magic).serialize(w)?;
        Uint32::from(self.version).serialize(w)?;
        for section in self.sections.into_iter() {
            section.serialize(w)?;
        }
        Ok(())
    }
}

#[cfg(test)]
mod integration_tests {

    use super::super::{deserialize_file, serialize, deserialize_buffer, Section};
    use super::Module;

    #[test]
    fn hello() {
        let module = deserialize_file("./res/cases/v1/hello.wasm").expect("Should be deserialized");

        assert_eq!(module.version(), 1);
        assert_eq!(module.sections().len(), 8);
    }

    #[test]
    fn serde() {
        let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        let buf = serialize(module).expect("serialization to succeed");

        let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
        let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");

        assert_eq!(module_old.sections().len(), module_new.sections().len());
    }

    #[test]
    fn serde_type() {
        let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        module.sections_mut().retain(|x| {
            if let &Section::Type(_) = x { true } else { false }
        });

        let buf = serialize(module).expect("serialization to succeed");

        let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
        let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        assert_eq!(
            module_old.type_section().expect("type section exists").types().len(),
            module_new.type_section().expect("type section exists").types().len(),
            "There should be equal amount of types before and after serialization"
        );
    }

    #[test]
    fn serde_import() {
        let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        module.sections_mut().retain(|x| {
            if let &Section::Import(_) = x { true } else { false }
        });

        let buf = serialize(module).expect("serialization to succeed");

        let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
        let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        assert_eq!(
            module_old.import_section().expect("import section exists").entries().len(),
            module_new.import_section().expect("import section exists").entries().len(),
            "There should be equal amount of import entries before and after serialization"
        );
    }

    #[test]
    fn serde_code() {
        let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        module.sections_mut().retain(|x| {
            if let &Section::Code(_) = x { true } else { false }
        });

        let buf = serialize(module).expect("serialization to succeed");

        let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
        let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
        assert_eq!(
            module_old.code_section().expect("code section exists").bodies().len(),
            module_new.code_section().expect("code section exists").bodies().len(),
            "There should be equal amount of function bodies before and after serialization"
        );
    }

    #[test]
    fn const_() {
        use super::super::Opcode::*;

        let module = deserialize_file("./res/cases/v1/const.wasm").expect("Should be deserialized");
        let func = &module.code_section().expect("Code section to exist").bodies()[0];
        assert_eq!(func.code().elements().len(), 14);

        assert_eq!(I32Const(1024), func.code().elements()[0]);
        assert_eq!(I32Const(2048), func.code().elements()[1]);
        assert_eq!(I32Const(4096), func.code().elements()[2]);
        assert_eq!(I32Const(8192), func.code().elements()[3]);
        assert_eq!(I32Const(16384), func.code().elements()[4]);
        assert_eq!(I32Const(32767), func.code().elements()[5]);
        assert_eq!(I32Const(-1024), func.code().elements()[6]);
        assert_eq!(I32Const(-2048), func.code().elements()[7]);
        assert_eq!(I32Const(-4096), func.code().elements()[8]);
        assert_eq!(I32Const(-8192), func.code().elements()[9]);
        assert_eq!(I32Const(-16384), func.code().elements()[10]);
        assert_eq!(I32Const(-32768), func.code().elements()[11]);
    }
}<|endoftext|>


<commit_before>// -*- rust -*-
// error-pattern:1 == 2
use std;
import std::task;
import std::comm::port;
import std::comm::recv;

fn child() { assert (1 == 2); }

fn parent() {
    // Since this task isn't supervised it won't bring down the whole
    // process
    task::unsupervise();
    let p = port::<int>();
    let f = child;
    task::spawn(f);
    let x = recv(p);
}

fn main() {
    let f = parent;
    task::spawn(f);
}<commit_msg>Remove a spurious error pattern from run-pass/linked-failure<commit_after>// -*- rust -*-
use std;
import std::task;
import std::comm::port;
import std::comm::recv;

fn child() { assert (1 == 2); }

fn parent() {
    // Since this task isn't supervised it won't bring down the whole
    // process
    task::unsupervise();
    let p = port::<int>();
    let f = child;
    task::spawn(f);
    let x = recv(p);
}

fn main() {
    let f = parent;
    task::spawn(f);
}<|endoftext|>


<commit_before><commit_msg>add unwrap to var lookup in fixtures<commit_after><|endoftext|>


<commit_before><commit_msg>Fix one more test case<commit_after><|endoftext|>


<commit_before>#[macro_use]
extern crate objc;

use objc::Encode;
use objc::runtime::{Class, Object};

/// Wrapper around an `Object` pointer that will release it when dropped.
struct StrongPtr(*mut Object);

impl std::ops::Deref for StrongPtr {
    type Target = Object;

    fn deref(&self) -> &Object {
        unsafe { &*self.0 }
    }
}

impl Drop for StrongPtr {
    fn drop(&mut self) {
        let _: () = unsafe { msg_send![self.0, release] };
    }
}

fn main() {
    // Get a class
    let cls = class!(NSObject);
    println!("NSObject size: {}", cls.instance_size());

    // Inspect its ivars
    println!("NSObject ivars:");
    for ivar in cls.instance_variables().iter() {
        println!("{}", ivar.name());
    }

    // Allocate an instance
    let obj = unsafe {
        let obj: *mut Object = msg_send![cls, alloc];
        let obj: *mut Object = msg_send![obj, init];
        StrongPtr(obj)
    };
    println!("NSObject address: {:p}", &*obj);

    // Access an ivar of the object
    let isa: *const Class = unsafe {
        *obj.get_ivar("isa")
    };
    println!("NSObject isa: {:?}", isa);

    // Inspect a method of the class
    let hash_sel = sel!(hash);
    let hash_method = cls.instance_method(hash_sel).unwrap();
    let hash_return = hash_method.return_type();
    println!("-[NSObject hash] return type: {:?}", hash_return);
    assert!(hash_return == usize::encode());

    // Invoke a method on the object
    let hash: usize = unsafe {
        msg_send![obj, hash]
    };
    println!("NSObject hash: {}", hash);
}
<commit_msg>Update example to use the provided StrongPtr<commit_after>#[macro_use]
extern crate objc;

use objc::Encode;
use objc::rc::StrongPtr;
use objc::runtime::{Class, Object};

fn main() {
    // Get a class
    let cls = class!(NSObject);
    println!("NSObject size: {}", cls.instance_size());

    // Inspect its ivars
    println!("NSObject ivars:");
    for ivar in cls.instance_variables().iter() {
        println!("{}", ivar.name());
    }

    // Allocate an instance
    let obj = unsafe {
        let obj: *mut Object = msg_send![cls, alloc];
        let obj: *mut Object = msg_send![obj, init];
        StrongPtr::new(obj)
    };
    println!("NSObject address: {:p}", obj);

    // Access an ivar of the object
    let isa: *const Class = unsafe {
        *(**obj).get_ivar("isa")
    };
    println!("NSObject isa: {:?}", isa);

    // Inspect a method of the class
    let hash_sel = sel!(hash);
    let hash_method = cls.instance_method(hash_sel).unwrap();
    let hash_return = hash_method.return_type();
    println!("-[NSObject hash] return type: {:?}", hash_return);
    assert!(hash_return == usize::encode());

    // Invoke a method on the object
    let hash: usize = unsafe {
        msg_send![*obj, hash]
    };
    println!("NSObject hash: {}", hash);
}
<|endoftext|>


<commit_before>use std::io::{self, BufRead, BufReader, BufWriter, Write};

use serde_json::Value;

use crate::protocol::{
    read_message, write_error_response, write_success_response, write_success_result, ErrorCodes,
    Message, NotificationMessage, RequestMessage, ResponseError,
};

use crate::{Error, Result};

#[derive(PartialEq)]
enum State {
    Initialized,
    ShuttingDown,
}

struct ServerContext {
    state: State,
    // Set when `exit` notification is received.
    exit_code: Option<i32>,
}

impl ServerContext {
    fn new() -> ServerContext {
        ServerContext {
            state: State::Initialized,
            exit_code: None,
        }
    }
}

fn create_server_capabilities() -> lsp_types::ServerCapabilities {
    let options = lsp_types::TextDocumentSyncOptions {
        open_close: Some(true),
        change: Some(lsp_types::TextDocumentSyncKind::Full),
        will_save: Some(true),
        will_save_wait_until: Some(false),
        save: None,
    };

    let text_document_sync = lsp_types::TextDocumentSyncCapability::Options(options);

    lsp_types::ServerCapabilities {
        text_document_sync: Some(text_document_sync),
        hover_provider: None,
        completion_provider: None,
        signature_help_provider: None,
        definition_provider: None,
        type_definition_provider: None,
        implementation_provider: None,
        references_provider: None,
        document_highlight_provider: None,
        document_symbol_provider: None,
        workspace_symbol_provider: None,
        code_action_provider: None,
        code_lens_provider: None,
        document_formatting_provider: None,
        document_range_formatting_provider: None,
        document_on_type_formatting_provider: None,
        rename_provider: None,
        color_provider: None,
        folding_range_provider: None,
        execute_command_provider: None,
        workspace: None,
    }
}

// Requests

fn handle_request(
    writer: &mut impl Write,
    ctx: &mut ServerContext,
    msg: RequestMessage,
) -> Result<()> {
    let id = msg.id;
    let method = msg.method.as_str();

    let res = match method {
        "initialize" => initialize_request(),
        "shutdown" => shutdown_request(ctx),
        _ => unimplemented!(),
    };
    match res {
        Ok(res) => write_success_response(writer, id, res)?,
        Err(error) => write_error_response(writer, id, error)?,
    }
    Ok(())
}

type MessageResult<T> = std::result::Result<T, ResponseError>;

fn initialize_request() -> MessageResult<Value> {
    // The server has been initialized already.
    let error_message = "Unexpected initialize message".to_owned();
    Err(ResponseError::new(
        ErrorCodes::ServerNotInitialized,
        error_message,
    ))
}

fn shutdown_request(ctx: &mut ServerContext) -> MessageResult<Value> {
    ctx.state = State::ShuttingDown;
    Ok(Value::Null)
}

// Notifications

fn handle_notification(
    _write: &mut impl Write,
    ctx: &mut ServerContext,
    msg: NotificationMessage,
) -> Result<()> {
    let method = msg.method.as_str();
    eprintln!("Got notification: {}", method);
    match method {
        "exit" => exit_notification(ctx),
        _ => unimplemented!(),
    }
}

fn exit_notification(ctx: &mut ServerContext) -> Result<()> {
    // https://microsoft.github.io/language-server-protocol/specification#exit
    if ctx.state == State::ShuttingDown {
        ctx.exit_code = Some(0);
    } else {
        ctx.exit_code = Some(1);
    }
    Ok(())
}

fn initialize(
    reader: &mut impl BufRead,
    writer: &mut impl Write,
) -> Result<lsp_types::InitializeParams> {
    let message = read_message(reader)?;

    let (id, params) = match message {
        Message::Request(req) => req.cast::<lsp_types::request::Initialize>()?,
        _ => {
            // TODO: Gracefully handle `exit` and `shutdown` messages.
            let error_message = format!("Expected initialize message but got {:?}", message);
            return Err(Error::ProtocolError(error_message));
        }
    };

    let capabilities = create_server_capabilities();
    let res = lsp_types::InitializeResult {
        capabilities: capabilities,
    };
    write_success_result(writer, id, res)?;

    let message = read_message(reader)?;
    match message {
        Message::Notofication(notif) => notif.cast::<lsp_types::notification::Initialized>()?,
        _ => {
            let error_message = format!("Expected initialized message but got {:?}", message);
            return Err(Error::ProtocolError(error_message));
        }
    };

    Ok(params)
}

// Returns exit code.
pub fn start() -> Result<i32> {
    let mut reader = BufReader::new(io::stdin());
    let mut writer = BufWriter::new(io::stdout());

    let _params = initialize(&mut reader, &mut writer)?;

    let mut ctx = ServerContext::new();

    loop {
        eprintln!("Reading message...");
        let message = read_message(&mut reader)?;
        match message {
            Message::Request(request) => handle_request(&mut writer, &mut ctx, request)?,
            Message::Notofication(notification) => {
                handle_notification(&mut writer, &mut ctx, notification)?
            }
            _ => unimplemented!(),
        };

        if let Some(exit_code) = ctx.exit_code {
            return Ok(exit_code);
        }
    }
}
<commit_msg>Add did_{open,change}_text_document()<commit_after>use std::io::{self, BufRead, BufReader, BufWriter, Write};

use serde_json::Value;

use crate::protocol::{
    read_message, write_error_response, write_success_response, write_success_result, ErrorCodes,
    Message, NotificationMessage, RequestMessage, ResponseError,
};

use crate::{Error, Result};

#[derive(PartialEq)]
enum State {
    Initialized,
    ShuttingDown,
}

struct ServerContext {
    state: State,
    // Set when `exit` notification is received.
    exit_code: Option<i32>,
}

impl ServerContext {
    fn new() -> ServerContext {
        ServerContext {
            state: State::Initialized,
            exit_code: None,
        }
    }
}

fn create_server_capabilities() -> lsp_types::ServerCapabilities {
    let options = lsp_types::TextDocumentSyncOptions {
        open_close: Some(true),
        change: Some(lsp_types::TextDocumentSyncKind::Full),
        will_save: Some(true),
        will_save_wait_until: Some(false),
        save: None,
    };

    let text_document_sync = lsp_types::TextDocumentSyncCapability::Options(options);

    lsp_types::ServerCapabilities {
        text_document_sync: Some(text_document_sync),
        hover_provider: None,
        completion_provider: None,
        signature_help_provider: None,
        definition_provider: None,
        type_definition_provider: None,
        implementation_provider: None,
        references_provider: None,
        document_highlight_provider: None,
        document_symbol_provider: None,
        workspace_symbol_provider: None,
        code_action_provider: None,
        code_lens_provider: None,
        document_formatting_provider: None,
        document_range_formatting_provider: None,
        document_on_type_formatting_provider: None,
        rename_provider: None,
        color_provider: None,
        folding_range_provider: None,
        execute_command_provider: None,
        workspace: None,
    }
}

// Requests

fn handle_request(
    writer: &mut impl Write,
    ctx: &mut ServerContext,
    msg: RequestMessage,
) -> Result<()> {
    let id = msg.id;
    let method = msg.method.as_str();

    let res = match method {
        "initialize" => initialize_request(),
        "shutdown" => shutdown_request(ctx),
        _ => unimplemented!(),
    };
    match res {
        Ok(res) => write_success_response(writer, id, res)?,
        Err(error) => write_error_response(writer, id, error)?,
    }
    Ok(())
}

type MessageResult<T> = std::result::Result<T, ResponseError>;

fn initialize_request() -> MessageResult<Value> {
    // The server has been initialized already.
    let error_message = "Unexpected initialize message".to_owned();
    Err(ResponseError::new(
        ErrorCodes::ServerNotInitialized,
        error_message,
    ))
}

fn shutdown_request(ctx: &mut ServerContext) -> MessageResult<Value> {
    ctx.state = State::ShuttingDown;
    Ok(Value::Null)
}

// Notifications

fn get_params<P: serde::de::DeserializeOwned>(params: Value) -> Result<P> {
    serde_json::from_value::<P>(params).map_err(|err| Error::ProtocolError(err.to_string()))
}

fn handle_notification(
    _write: &mut impl Write,
    ctx: &mut ServerContext,
    msg: NotificationMessage,
) -> Result<()> {
    let method = msg.method.as_str();
    eprintln!("Got notification: {}", method);

    use lsp_types::notification::*;
    match msg.method.as_str() {
        Exit::METHOD => exit_notification(ctx),
        DidOpenTextDocument::METHOD => {
            get_params(msg.params).and_then(|params| did_open_text_document(params))
        }
        DidChangeTextDocument::METHOD => {
            get_params(msg.params).and_then(|params| did_change_text_document(params))
        }
        _ => unimplemented!(),
    }
}

fn exit_notification(ctx: &mut ServerContext) -> Result<()> {
    // https://microsoft.github.io/language-server-protocol/specification#exit
    if ctx.state == State::ShuttingDown {
        ctx.exit_code = Some(0);
    } else {
        ctx.exit_code = Some(1);
    }
    Ok(())
}

fn did_open_text_document(_params: lsp_types::DidOpenTextDocumentParams) -> Result<()> {
    use lsp_types::notification::Notification;
    eprintln!(
        "Received {}: {:?}",
        lsp_types::notification::DidOpenTextDocument::METHOD,
        _params.text_document
    );
    Ok(())
}

fn did_change_text_document(_params: lsp_types::DidChangeTextDocumentParams) -> Result<()> {
    use lsp_types::notification::Notification;
    eprintln!(
        "Received {}: {:?}",
        lsp_types::notification::DidChangeTextDocument::METHOD,
        _params.text_document
    );
    Ok(())
}

// Initialization

fn initialize(
    reader: &mut impl BufRead,
    writer: &mut impl Write,
) -> Result<lsp_types::InitializeParams> {
    let message = read_message(reader)?;

    let (id, params) = match message {
        Message::Request(req) => req.cast::<lsp_types::request::Initialize>()?,
        _ => {
            // TODO: Gracefully handle `exit` and `shutdown` messages.
            let error_message = format!("Expected initialize message but got {:?}", message);
            return Err(Error::ProtocolError(error_message));
        }
    };

    let capabilities = create_server_capabilities();
    let res = lsp_types::InitializeResult {
        capabilities: capabilities,
    };
    write_success_result(writer, id, res)?;

    let message = read_message(reader)?;
    match message {
        Message::Notofication(notif) => notif.cast::<lsp_types::notification::Initialized>()?,
        _ => {
            let error_message = format!("Expected initialized message but got {:?}", message);
            return Err(Error::ProtocolError(error_message));
        }
    };

    Ok(params)
}

// Returns exit code.
pub fn start() -> Result<i32> {
    let mut reader = BufReader::new(io::stdin());
    let mut writer = BufWriter::new(io::stdout());

    let _params = initialize(&mut reader, &mut writer)?;

    let mut ctx = ServerContext::new();

    loop {
        eprintln!("Reading message...");
        let message = read_message(&mut reader)?;
        match message {
            Message::Request(request) => handle_request(&mut writer, &mut ctx, request)?,
            Message::Notofication(notification) => {
                handle_notification(&mut writer, &mut ctx, notification)?
            }
            _ => unimplemented!(),
        };

        if let Some(exit_code) = ctx.exit_code {
            return Ok(exit_code);
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate gfx;
extern crate ggez;

use ggez::*;
use ggez::event::*;
use ggez::graphics::*;
use std::env;
use std::path;

gfx_defines!{
    constant Light {
        color: [f32; 4] = "u_Color",
        pos: [f32; 2] = "u_Pos",
        screen_size: [f32; 2] = "u_ScreenSize",
        glow: f32 = "u_Glow",
        strength: f32 = "u_Strength",
    }
}

const OCCLUSIONS_SHADER_SOURCE: &[u8] = b"#version 150 core

uniform sampler2D t_Texture;
in vec2 v_Uv;
out vec4 Target0;

layout (std140) uniform Light {
    vec4 u_Color;
    vec2 u_Pos;
    vec2 u_ScreenSize;
    float u_Glow;
    float u_Strength;
};

void main() {
    float dist = 1.0;
    float theta = radians(v_Uv.x * 360.0);
    vec2 dir = vec2(cos(theta), sin(theta));
    vec2 pos = u_Pos / u_ScreenSize;
    for(int i = 0; i < 1024; i++) {
        float fi = i;
        float r = fi / 1024.0;
        vec2 rel = r * dir;
        vec2 p = clamp(pos+rel, 0.0, 1.0);
        if (texture(t_Texture, p).a == 1.0) {
            dist = distance(pos, p) * 0.5;
            break;
        }
    }

    float others = dist == 1.0 ? 0.0 : dist;
    Target0 = vec4(dist, others, others, 1.0);
}
";

const SHADOWS_SHADER_SOURCE: &[u8] = b"#version 150 core

uniform sampler2D t_Texture;
in vec2 v_Uv;
out vec4 Target0;

layout (std140) uniform Light {
    vec4 u_Color;
    vec2 u_Pos;
    vec2 u_ScreenSize;
    float u_Glow;
    float u_Strength;
};

void main() {
    vec2 coord = gl_FragCoord.xy / u_ScreenSize;
    vec2 pos = u_Pos / u_ScreenSize;

    vec2 rel = coord - pos;
    float theta = atan(rel.y, rel.x);
    float ox = degrees(theta) / 360.0;
    if (ox < 0) {
        ox += 1.0;
    }
    float r = length(rel);
    float occl = texture(t_Texture, vec2(ox, 0.5)).r * 2.0;

    float intencity = 1.0;
    if (r < occl) {
        float p = u_Strength + u_Glow;
        float d = distance(gl_FragCoord.xy, u_Pos);
        intencity = 1.0 - clamp(p/(d*d), 0.0, 1.0);
    }

    Target0 = vec4(0.0, 0.0, 0.0, intencity);
}
";

struct MainState {
    background: Image,
    tile: Image,
    text: Text,
    light: Light,
    foreground: Canvas,
    occlusions: Canvas,
    occlusions_shader: PixelShader<Light>,
    shadows_shader: PixelShader<Light>,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let background = Image::new(ctx, "/background.png")?;
        let tile = Image::new(ctx, "/tile.png")?;
        let text = {
            let font = Font::new(ctx, "/DejaVuSerif.ttf", 48)?;
            Text::new(ctx, "SHADOWS...", &font)?
        };
        let screen_size = {
            let coords = graphics::get_screen_coordinates(ctx);
            [coords.w, coords.h.abs()]
        };
        let light = Light {
            pos: [0.0, 0.0],
            color: [0.7, 0.64, 0.34, 1.0],
            screen_size,
            glow: 0.0,
            strength: 2500.0,
        };
        let foreground = Canvas::with_window_size(ctx)?;
        let occlusions = Canvas::new(ctx, 360, 1)?;
        let occlusions_shader =
            PixelShader::from_u8(ctx, OCCLUSIONS_SHADER_SOURCE, light, "Light")?;
        let shadows_shader = PixelShader::from_u8(ctx, SHADOWS_SHADER_SOURCE, light, "Light")?;

        Ok(MainState {
            background,
            tile,
            text,
            light,
            foreground,
            occlusions,
            occlusions_shader,
            shadows_shader,
        })
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
        self.light.glow = 200.0 * ((timer::get_ticks(ctx) as f32) / 20.0).cos();
        self.occlusions_shader.send(ctx, self.light)?;
        self.shadows_shader.send(ctx, self.light)?;

        if timer::get_ticks(ctx) % 100 == 0 {
            println!("Delta frame time: {:?} ", timer::get_delta(ctx));
            println!("Average FPS: {}", timer::get_fps(ctx));
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        let center = DrawParam {
            dest: Point2::new(
                self.light.screen_size[0] / 2.0,
                self.light.screen_size[1] / 2.0,
            ),
            ..Default::default()
        };

        graphics::set_canvas(ctx, Some(&self.foreground));
        graphics::set_background_color(ctx, [0.0; 4].into());
        graphics::draw_ex(
            ctx,
            &self.tile,
            DrawParam {
                dest: Point2::new(598.0, 124.0),
                ..Default::default()
            },
        )?;
        graphics::draw_ex(
            ctx,
            &self.tile,
            DrawParam {
                dest: Point2::new(92.0, 350.0),
                ..Default::default()
            },
        )?;
        graphics::draw_ex(
            ctx,
            &self.tile,
            DrawParam {
                dest: Point2::new(442.0, 468.0),
                rotation: 0.5,
                ..Default::default()
            },
        )?;
        graphics::draw_ex(ctx, &self.text, center)?;

        {
            let _shader_lock = graphics::use_shader(ctx, &self.occlusions_shader);
            graphics::set_canvas(ctx, Some(&self.occlusions));
            graphics::draw_ex(ctx, &self.foreground, center)?;
        }

        graphics::set_canvas(ctx, None);
        graphics::set_color(ctx, self.light.color.into())?;
        graphics::clear(ctx);
        graphics::draw_ex(ctx, &self.background, center)?;
        {
            let _shader_lock = graphics::use_shader(ctx, &self.shadows_shader);
            let param = DrawParam {
                scale: Point2::new(self.light.screen_size[0] / 360.0, self.light.screen_size[1]),
                ..center
            };
            graphics::draw_ex(ctx, &self.occlusions, param)?;
        }
        graphics::draw_ex(ctx, &self.foreground, center)?;

        // Uncomment following two lines to visualize the 1D occlusions canvas
        // graphics::set_color(ctx, [1.0; 4].into())?;
        // graphics::draw_ex(ctx, &self.occlusions, center)?;

        graphics::present(ctx);
        Ok(())
    }

    fn mouse_motion_event(
        &mut self,
        ctx: &mut Context,
        _state: MouseState,
        x: i32,
        y: i32,
        _xrel: i32,
        _yrel: i32,
    ) {
        let pos = {
            let pos = Point2::new(x as f32, y as f32);
            graphics::convert_screen_coordinates(ctx, pos)
        };
        self.light.pos = [pos.x, pos.y];
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("shadows", "ggez", c).unwrap();

    // We add the CARGO_MANIFEST_DIR/resources do the filesystems paths so
    // we we look in the cargo project for files.
    if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        ctx.filesystem.mount(&path, true);
    }

    let state = &mut MainState::new(ctx).unwrap();
    event::run(ctx, state).unwrap();
}
<commit_msg>added a bunch of comments to explain what is going on<commit_after>#[macro_use]
extern crate gfx;
extern crate ggez;

use ggez::*;
use ggez::event::*;
use ggez::graphics::*;
use std::env;
use std::path;

gfx_defines!{
    /// Constants used by the shaders to calculate
    constant Light {
        color: [f32; 4] = "u_Color",
        pos: [f32; 2] = "u_Pos",
        screen_size: [f32; 2] = "u_ScreenSize",
        glow: f32 = "u_Glow",
        strength: f32 = "u_Strength",
    }
}

/// Shader source for calculating a 1D shadow map that encodes half distances
/// in the red channel. The idea is that we scan X rays (X is the horizontal
/// size of the output) and calculate the distance to the nearest pixel at that
/// angle that has transparency above a threashold. The distance gets halved
/// and encoded in the red channel (it is havled because if the distance can be
/// greater than 1.0 - think bottom left to top right corner, that sqrt(1) and
/// will not get properly encoded).
const OCCLUSIONS_SHADER_SOURCE: &[u8] = b"#version 150 core

uniform sampler2D t_Texture;
in vec2 v_Uv;
out vec4 Target0;

layout (std140) uniform Light {
    vec4 u_Color;
    vec2 u_Pos;
    vec2 u_ScreenSize;
    float u_Glow;
    float u_Strength;
};

void main() {
    float dist = 1.0;
    float theta = radians(v_Uv.x * 360.0);
    vec2 dir = vec2(cos(theta), sin(theta));
    vec2 pos = u_Pos / u_ScreenSize;
    for(int i = 0; i < 1024; i++) {
        float fi = i;
        float r = fi / 1024.0;
        vec2 rel = r * dir;
        vec2 p = clamp(pos+rel, 0.0, 1.0);
        if (texture(t_Texture, p).a > 0.8) {
            dist = distance(pos, p) * 0.5;
            break;
        }
    }

    float others = dist == 1.0 ? 0.0 : dist;
    Target0 = vec4(dist, others, others, 1.0);
}
";

/// Shader for drawing shadows based on a 1D shadow map. It takes current
/// fragment cordinates and converts them to polar coordinates centered
/// around the light source, using the angle to sample from the 1D shadow map.
/// If the distance from the light source is greater than the distance of the
/// closest reported shadow, then the output is black, else it calculates some
/// shadow based on the distance from light source based on strength and glow
/// uniform parameters.
const SHADOWS_SHADER_SOURCE: &[u8] = b"#version 150 core

uniform sampler2D t_Texture;
in vec2 v_Uv;
out vec4 Target0;

layout (std140) uniform Light {
    vec4 u_Color;
    vec2 u_Pos;
    vec2 u_ScreenSize;
    float u_Glow;
    float u_Strength;
};

void main() {
    vec2 coord = gl_FragCoord.xy / u_ScreenSize;
    vec2 pos = u_Pos / u_ScreenSize;

    vec2 rel = coord - pos;
    float theta = atan(rel.y, rel.x);
    float ox = degrees(theta) / 360.0;
    if (ox < 0) {
        ox += 1.0;
    }
    float r = length(rel);
    float occl = texture(t_Texture, vec2(ox, 0.5)).r * 2.0;

    float intencity = 1.0;
    if (r < occl) {
        float p = u_Strength + u_Glow;
        float d = distance(gl_FragCoord.xy, u_Pos);
        intencity = 1.0 - clamp(p/(d*d), 0.0, 1.0);
    }

    Target0 = vec4(0.0, 0.0, 0.0, intencity);
}
";

struct MainState {
    background: Image,
    tile: Image,
    text: Text,
    light: Light,
    foreground: Canvas,
    occlusions: Canvas,
    occlusions_shader: PixelShader<Light>,
    shadows_shader: PixelShader<Light>,
}

/// The default color for the light
const LIGHT_COLOR: [f32; 4] = [0.7, 0.64, 0.34, 1.0];
/// The number of rays to cast to. Increasing this number will result in better
/// quality shadows. If you increase too much you might hit some GPU shader
/// hardware limits.
const LIGHT_RAY_COUNT: u32 = 1440;
/// The strength of the light - how far it shines
const LIGHT_STRENGTH: f32 = 2500.0;
/// The factor at which the light glows - just for fun
const LIGHT_GLOW_FACTOR: f32 = 200.0;
/// The rate at which the glow effect oscillates
const LIGHT_GLOW_RATE: f32 = 20.0;

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let background = Image::new(ctx, "/background.png")?;
        let tile = Image::new(ctx, "/tile.png")?;
        let text = {
            let font = Font::new(ctx, "/DejaVuSerif.ttf", 48)?;
            Text::new(ctx, "SHADOWS...", &font)?
        };
        let screen_size = {
            let coords = graphics::get_screen_coordinates(ctx);
            [coords.w, coords.h.abs()]
        };
        let light = Light {
            pos: [0.0, 0.0],
            color: LIGHT_COLOR,
            screen_size,
            glow: 0.0,
            strength: LIGHT_STRENGTH,
        };
        let foreground = Canvas::with_window_size(ctx)?;
        let occlusions = Canvas::new(ctx, LIGHT_RAY_COUNT, 1)?;
        let occlusions_shader =
            PixelShader::from_u8(ctx, OCCLUSIONS_SHADER_SOURCE, light, "Light")?;
        let shadows_shader = PixelShader::from_u8(ctx, SHADOWS_SHADER_SOURCE, light, "Light")?;

        Ok(MainState {
            background,
            tile,
            text,
            light,
            foreground,
            occlusions,
            occlusions_shader,
            shadows_shader,
        })
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
        if timer::get_ticks(ctx) % 100 == 0 {
            println!("Average FPS: {}", timer::get_fps(ctx));
        }

        self.light.glow = LIGHT_GLOW_FACTOR * ((timer::get_ticks(ctx) as f32) / LIGHT_GLOW_RATE).cos();
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        let center = DrawParam {
            dest: Point2::new(
                self.light.screen_size[0] / 2.0,
                self.light.screen_size[1] / 2.0,
            ),
            ..Default::default()
        };

        // First thing we want to do it to render all the foreground items (that
        // will have shadows) onto their own Canvas (off-scree render). We will
        // use this canvas to:
        //  - run the occlusions shader to determine where the shadows are
        //  - render to screen once all the shadows are caculated and rendered
        graphics::set_canvas(ctx, Some(&self.foreground));
        graphics::set_background_color(ctx, [0.0; 4].into());
        graphics::clear(ctx);
        graphics::draw_ex(
            ctx,
            &self.tile,
            DrawParam {
                dest: Point2::new(598.0, 124.0),
                ..Default::default()
            },
        )?;
        graphics::draw_ex(
            ctx,
            &self.tile,
            DrawParam {
                dest: Point2::new(92.0, 350.0),
                ..Default::default()
            },
        )?;
        graphics::draw_ex(
            ctx,
            &self.tile,
            DrawParam {
                dest: Point2::new(442.0, 468.0),
                rotation: 0.5,
                ..Default::default()
            },
        )?;
        graphics::draw_ex(ctx, &self.text, center)?;

        // Now we want to run the occlusions shader to calculate our 1D shadow
        // distances into the `occlusions` canvas.
        {
            let _shader_lock = graphics::use_shader(ctx, &self.occlusions_shader);
            self.occlusions_shader.send(ctx, self.light)?;

            graphics::set_canvas(ctx, Some(&self.occlusions));
            graphics::draw_ex(ctx, &self.foreground, center)?;
        }

        // Now lets finally render to screen starting with out background, then
        // the shadows overtop and finally our foreground. Note that we set the
        // light color as the color for our render giving everything the "tint"
        // we desire.
        graphics::set_canvas(ctx, None);
        graphics::set_color(ctx, self.light.color.into())?; // color filter so things take the light color
        graphics::clear(ctx);
        graphics::draw_ex(ctx, &self.background, center)?;
        {
            let _shader_lock = graphics::use_shader(ctx, &self.shadows_shader);
            self.shadows_shader.send(ctx, self.light)?;

            let param = DrawParam {
                scale: Point2::new(self.light.screen_size[0] / (LIGHT_RAY_COUNT as f32), self.light.screen_size[1]),
                ..center
            };
            graphics::draw_ex(ctx, &self.occlusions, param)?;
        }
        graphics::draw_ex(ctx, &self.foreground, center)?;

        // Uncomment following two lines to visualize the 1D occlusions canvas,
        // red pixels represent angles at which no shadows were found, and then
        // the greyscale pixels are the half distances of the nearest shadows to
        // the mouse position (equally encoded in all color channels).
        // graphics::set_color(ctx, [1.0; 4].into())?;
        // graphics::draw_ex(ctx, &self.occlusions, center)?;

        graphics::present(ctx);
        Ok(())
    }

    fn mouse_motion_event(
        &mut self,
        ctx: &mut Context,
        _state: MouseState,
        x: i32,
        y: i32,
        _xrel: i32,
        _yrel: i32,
    ) {
        let pos = {
            let pos = Point2::new(x as f32, y as f32);
            graphics::convert_screen_coordinates(ctx, pos)
        };
        self.light.pos = [pos.x, pos.y];
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("shadows", "ggez", c).unwrap();

    // We add the CARGO_MANIFEST_DIR/resources do the filesystems paths so
    // we we look in the cargo project for files.
    if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        ctx.filesystem.mount(&path, true);
    }

    let state = &mut MainState::new(ctx).unwrap();
    event::run(ctx, state).unwrap();
}
<|endoftext|>


<commit_before>fn main() {
    // Iterators can be collected into vectors
    let collected_iterator: Vec<int> = range(0i, 10).collect();
    println!("Collected range(0, 10) into: {}", collected_iterator);

    // The `vec!` macro can be used to initialize a vector
    let mut xs = vec![1i, 2, 3];
    println!("Initial vector: {}", xs);

    // Insert new element at the end of the vector
    println!("Push 4 into the vector")
    xs.push(4);
    println!("Vector: {}", xs);

    // Error! Immutable vectors can't grow
    collected_iterator.push(0);
    // FIXME ^ Comment out this line

    // The `len` method yields the current size of the vector
    println!("Vector size: {}", xs.len());

    // Indexing is done using the `get` method (indexing starts at 0)
    println!("Second element: {}", xs.get(1));

    // `pop` removes the last element from the vector and returns it
    println!("Pop last element: {}", xs.pop());

    // Out of bounds indexing yields a task failure
    println!("Fourth element: {}", xs.get(3));
}
<commit_msg>No more Vec::get() method in rust<commit_after>fn main() {
    // Iterators can be collected into vectors
    let collected_iterator: Vec<int> = range(0i, 10).collect();
    println!("Collected range(0, 10) into: {}", collected_iterator);

    // The `vec!` macro can be used to initialize a vector
    let mut xs = vec![1i, 2, 3];
    println!("Initial vector: {}", xs);

    // Insert new element at the end of the vector
    println!("Push 4 into the vector")
    xs.push(4);
    println!("Vector: {}", xs);

    // Error! Immutable vectors can't grow
    collected_iterator.push(0);
    // FIXME ^ Comment out this line

    // The `len` method yields the current size of the vector
    println!("Vector size: {}", xs.len());

    // Indexing is done using the square brackets (indexing starts at 0)
    println!("Second element: {}", xs[1]);

    // `pop` removes the last element from the vector and returns it
    println!("Pop last element: {}", xs.pop());

    // Out of bounds indexing yields a task failure
    println!("Fourth element: {}", xs[3]);
}
<|endoftext|>