<commit_before>//! TODO Documentation

use wlroots_sys::{wl_output_transform, wlr_matrix_identity, wlr_matrix_mul, wlr_matrix_rotate,
                  wlr_matrix_scale, wlr_matrix_texture, wlr_matrix_transform, wlr_matrix_translate};

/// Modifies the matrix to become the identity matrix.
pub fn matrix_identity(output: &mut [f32; 16]) {
    unsafe { wlr_matrix_identity(output) }
}

/// Translate the matrix in the x, y, and z directions.
pub fn matrix_translate(output: &mut [f32; 16], x: f32, y: f32, z: f32) {
    unsafe { wlr_matrix_translate(output, x, y, z) }
}

/// Scale the output in the x, y, and z directions some amount.
pub fn matrix_scale(output: &mut [f32; 16], x: f32, y: f32, z: f32) {
    unsafe { wlr_matrix_scale(output, x, y, z) }
}

/// Rotate the matrix by some amount of radians.
pub fn matrix_rotate(output: &mut [f32; 16], radians: f32) {
    unsafe { wlr_matrix_rotate(output, radians) }
}

/// TODO Document
pub fn matrix_mul(x: &[f32; 16], y: &[f32; 16], product: &mut [f32; 16]) {
    unsafe { wlr_matrix_mul(x, y, product) }
}

/// Transform the matrix based on the given Wayland output transform mode.
pub fn matrix_transform(mat: &mut [f32; 16], transform: wl_output_transform) {
    unsafe { wlr_matrix_transform(mat.as_mut_ptr(), transform) }
}

/// Transform the matrix based on the given Wayland output transform mode and
/// the width and height of a texture.
pub fn matrix_texture(mat: &mut [f32; 16],
                      width: i32,
                      height: i32,
                      transform: wl_output_transform) {
    unsafe { wlr_matrix_texture(mat.as_mut_ptr(), width, height, transform) }
}
<commit_msg>Fixed matrix functions for latest wlroots change<commit_after>//! TODO Documentation

use wlroots_sys::{wl_output_transform, wlr_matrix_identity, wlr_matrix_mul, wlr_matrix_rotate,
                  wlr_matrix_scale, wlr_matrix_texture, wlr_matrix_transform, wlr_matrix_translate};

/// Modifies the matrix to become the identity matrix.
pub fn matrix_identity(output: &mut [f32; 16]) {
    unsafe { wlr_matrix_identity(output.as_mut_ptr()) }
}

/// Translate the matrix in the x, and y.
pub fn matrix_translate(output: &mut [f32; 16], x: f32, y: f32) {
    unsafe { wlr_matrix_translate(output.as_mut_ptr(), x, y) }
}

/// Scale the output in the x, and y.
pub fn matrix_scale(output: &mut [f32; 16], x: f32, y: f32) {
    unsafe { wlr_matrix_scale(output.as_mut_ptr(), x, y) }
}

/// Rotate the matrix by some amount of radians.
pub fn matrix_rotate(output: &mut [f32; 16], radians: f32) {
    unsafe { wlr_matrix_rotate(output.as_mut_ptr(), radians) }
}

/// TODO Document
pub fn matrix_mul(x: &[f32; 16], y: &[f32; 16], product: &mut [f32; 16]) {
    unsafe { wlr_matrix_mul(x, y, product) }
}

/// Transform the matrix based on the given Wayland output transform mode.
pub fn matrix_transform(mat: &mut [f32; 16], transform: wl_output_transform) {
    unsafe { wlr_matrix_transform(mat.as_mut_ptr(), transform) }
}

/// Transform the matrix based on the given Wayland output transform mode and
/// the width and height of a texture.
pub fn matrix_texture(mat: &mut [f32; 16],
                      width: i32,
                      height: i32,
                      transform: wl_output_transform) {
    unsafe { wlr_matrix_texture(mat.as_mut_ptr(), width, height, transform) }
}
<|endoftext|>


<commit_before>#![crate_name = "sdl_image"]
#![comment = "SDL_image binding"]
#![license = "MIT"]
#![crate_type = "lib"]

extern crate libc;
extern crate sdl;

use libc::c_int;

use sdl::get_error;
use sdl::video::Surface;

// Setup linking for all targets.
#[cfg(any(not(target_os = "macos"), not(mac_framework)))]
#[link(name = "SDL_image")]
extern {}

#[cfg(all(target_os = "macos", mac_framework))]
#[link(name = "SDL_image", kind = "framework")]
extern {}

pub mod ll {
    #![allow(non_camel_case_types)]

    use sdl::video::ll::SDL_Surface;

    use libc::{c_int, c_uint};
    use libc::types::os::arch::c95::c_schar;

    pub type IMG_InitFlags = c_uint;

    pub static IMG_INIT_JPG: IMG_InitFlags = 1;
    pub static IMG_INIT_PNG: IMG_InitFlags = 2;
    pub static IMG_INIT_TIF: IMG_InitFlags = 4;
    pub static IMG_INIT_WEBP: IMG_InitFlags = 8;

    extern "C" {
        pub fn IMG_Init(flags: c_int) -> c_int;
        pub fn IMG_Quit();
        pub fn IMG_Load(file: *const c_schar) -> *mut SDL_Surface;
    }
}

#[deriving(PartialEq, Eq)]
pub enum InitFlag {
    InitJPG = ll::IMG_INIT_JPG as int,
    InitPNG = ll::IMG_INIT_PNG as int,
    InitTIF = ll::IMG_INIT_TIF as int
}

pub fn init(flags: &[InitFlag]) -> Vec<InitFlag> {
    let bitflags = unsafe {
        ll::IMG_Init(flags.iter().fold(0i32, |flags, &flag| {
            flags | flag as c_int
        }))
    };

    let flags = [InitJPG,
        InitPNG,
        InitTIF];

    flags.iter().filter_map(|&flag| {
        if bitflags & (flag as c_int) != 0 { Some(flag) }
        else { None }
    }).collect()
}

pub fn load(file: &Path) -> Result<Surface, String> {
    let cfile = file.to_c_str();
    unsafe {
        let raw = ll::IMG_Load(cfile.as_ptr());

        if raw.is_null() {
            Err(get_error())
        } else {
            Ok(Surface { raw: raw, owned: true })
        }
    }
}

pub fn quit() {
    unsafe { ll::IMG_Quit(); }
}
<commit_msg>language changes: static -> const updates on sdl_image.<commit_after>#![crate_name = "sdl_image"]
#![comment = "SDL_image binding"]
#![license = "MIT"]
#![crate_type = "lib"]

extern crate libc;
extern crate sdl;

use libc::c_int;

use sdl::get_error;
use sdl::video::Surface;

// Setup linking for all targets.
#[cfg(any(not(target_os = "macos"), not(mac_framework)))]
#[link(name = "SDL_image")]
extern {}

#[cfg(all(target_os = "macos", mac_framework))]
#[link(name = "SDL_image", kind = "framework")]
extern {}

pub mod ll {
    #![allow(non_camel_case_types)]

    use sdl::video::ll::SDL_Surface;

    use libc::{c_int, c_uint};
    use libc::types::os::arch::c95::c_schar;

    pub type IMG_InitFlags = c_uint;

    pub const IMG_INIT_JPG: IMG_InitFlags = 1;
    pub const IMG_INIT_PNG: IMG_InitFlags = 2;
    pub const IMG_INIT_TIF: IMG_InitFlags = 4;
    pub const IMG_INIT_WEBP: IMG_InitFlags = 8;

    extern "C" {
        pub fn IMG_Init(flags: c_int) -> c_int;
        pub fn IMG_Quit();
        pub fn IMG_Load(file: *const c_schar) -> *mut SDL_Surface;
    }
}

#[deriving(PartialEq, Eq)]
pub enum InitFlag {
    InitJPG = ll::IMG_INIT_JPG as int,
    InitPNG = ll::IMG_INIT_PNG as int,
    InitTIF = ll::IMG_INIT_TIF as int
}

pub fn init(flags: &[InitFlag]) -> Vec<InitFlag> {
    let bitflags = unsafe {
        ll::IMG_Init(flags.iter().fold(0i32, |flags, &flag| {
            flags | flag as c_int
        }))
    };

    let flags = [InitJPG,
        InitPNG,
        InitTIF];

    flags.iter().filter_map(|&flag| {
        if bitflags & (flag as c_int) != 0 { Some(flag) }
        else { None }
    }).collect()
}

pub fn load(file: &Path) -> Result<Surface, String> {
    let cfile = file.to_c_str();
    unsafe {
        let raw = ll::IMG_Load(cfile.as_ptr());

        if raw.is_null() {
            Err(get_error())
        } else {
            Ok(Surface { raw: raw, owned: true })
        }
    }
}

pub fn quit() {
    unsafe { ll::IMG_Quit(); }
}
<|endoftext|>


<commit_before>
use Dimension;
use {Shape, StrideShape};
use Ix;
use dimension::IntoDimension;

/// A trait for `Shape` and `D where D: Dimension` that allows
/// customizing the memory layout (strides) of an array shape.
///
/// This trait is used together with array constructor methods like
/// `Array::from_shape_vec`.
pub trait ShapeBuilder {
    type Dim: Dimension;
    type Strides;

    fn f(self) -> Shape<Self::Dim>;
    fn set_f(self, is_f: bool) -> Shape<Self::Dim>;
    fn strides(self, strides: Self::Strides) -> StrideShape<Self::Dim>;
}

pub trait IntoShape {
    type Dim: Dimension;
    fn into_shape(self) -> Shape<Self::Dim>;
}

impl<D> IntoShape for D
    where D: IntoDimension,
{
    type Dim = D::Dim;
    fn into_shape(self) -> Shape<Self::Dim> {
        Shape {
            dim: self.into_dimension(),
            is_c: true,
        }
    }
}
impl<D> IntoShape for Shape<D>
    where D: Dimension,
{
    type Dim = D;
    fn into_shape(self) -> Shape<Self::Dim> {
        self
    }
}
/*

impl IntoShape for () {
    type Dim = [Ix; 0];
    fn into_shape(self) -> Shape<Self::Dim> {
        Shape {
            dim: [],
            is_c: true,
        }
    }
}

impl IntoShape for Ix {
    type Dim = [Ix; 1];
    fn into_shape(self) -> Shape<Self::Dim> {
        Shape {
            dim: [self],
            is_c: true,
        }
    }
}

impl IntoShape for (Ix, Ix) {
    type Dim = [Ix; 2];
    fn into_shape(self) -> Shape<Self::Dim> {
        Shape {
            dim: [self.0, self.1],
            is_c: true,
        }
    }
}
*/

impl<D> From<D> for Shape<D>
    where D: Dimension
{
    fn from(d: D) -> Self {
        Shape {
            dim: d,
            is_c: true,
        }
    }
}

impl From<Ix> for Shape<[Ix; 1]>
{
    fn from(ix: Ix) -> Self {
        Shape {
            dim: [ix],
            is_c: true,
        }
    }
}

impl From<(Ix, Ix)> for Shape<[Ix; 2]>
{
    fn from(ix: (Ix, Ix)) -> Self {
        Shape {
            dim: [ix.0, ix.1],
            is_c: true,
        }
    }
}

impl<T, D> From<T> for StrideShape<D>
    where D: Dimension,
          T: IntoShape<Dim=D>,
{
    fn from(value: T) -> Self {
        let shape = value.into_shape();
        let d = shape.dim;
        let st = if shape.is_c { d.default_strides() } else { d.fortran_strides() };
        StrideShape {
            strides: st,
            dim: d,
            custom: false,
        }
    }
}

/*
impl<D> From<Shape<D>> for StrideShape<D>
    where D: Dimension
{
    fn from(shape: Shape<D>) -> Self {
        let d = shape.dim;
        let st = if shape.is_c { d.default_strides() } else { d.fortran_strides() };
        StrideShape {
            strides: st,
            dim: d,
            custom: false,
        }
    }
}
*/

impl<T> ShapeBuilder for T
    where T: IntoDimension
{
    type Dim = T::Dim;
    type Strides = T;
    fn f(self) -> Shape<Self::Dim> { self.set_f(true) }
    fn set_f(self, is_f: bool) -> Shape<Self::Dim> {
        self.into_shape().set_f(is_f)
    }
    fn strides(self, st: T) -> StrideShape<Self::Dim> {
        self.into_shape().strides(st.into_dimension())
    }
}

impl<D> ShapeBuilder for Shape<D>
    where D: Dimension
{
    type Dim = D;
    type Strides = D;
    fn f(self) -> Self { self.set_f(true) }
    fn set_f(mut self, is_f: bool) -> Self {
        self.is_c = !is_f;
        self
    }
    fn strides(self, st: D) -> StrideShape<D> {
        StrideShape {
            dim: self.dim,
            strides: st,
            custom: true,
        }
    }
}

<commit_msg>Shape: Add .size() method<commit_after>
use Dimension;
use {Shape, StrideShape};
use Ix;
use dimension::IntoDimension;

/// A trait for `Shape` and `D where D: Dimension` that allows
/// customizing the memory layout (strides) of an array shape.
///
/// This trait is used together with array constructor methods like
/// `Array::from_shape_vec`.
pub trait ShapeBuilder {
    type Dim: Dimension;
    type Strides;

    fn f(self) -> Shape<Self::Dim>;
    fn set_f(self, is_f: bool) -> Shape<Self::Dim>;
    fn strides(self, strides: Self::Strides) -> StrideShape<Self::Dim>;
}

pub trait IntoShape {
    type Dim: Dimension;
    fn into_shape(self) -> Shape<Self::Dim>;
}

impl<D> IntoShape for D
    where D: IntoDimension,
{
    type Dim = D::Dim;
    fn into_shape(self) -> Shape<Self::Dim> {
        Shape {
            dim: self.into_dimension(),
            is_c: true,
        }
    }
}
impl<D> IntoShape for Shape<D>
    where D: Dimension,
{
    type Dim = D;
    fn into_shape(self) -> Shape<Self::Dim> {
        self
    }
}
/*

impl IntoShape for () {
    type Dim = [Ix; 0];
    fn into_shape(self) -> Shape<Self::Dim> {
        Shape {
            dim: [],
            is_c: true,
        }
    }
}

impl IntoShape for Ix {
    type Dim = [Ix; 1];
    fn into_shape(self) -> Shape<Self::Dim> {
        Shape {
            dim: [self],
            is_c: true,
        }
    }
}

impl IntoShape for (Ix, Ix) {
    type Dim = [Ix; 2];
    fn into_shape(self) -> Shape<Self::Dim> {
        Shape {
            dim: [self.0, self.1],
            is_c: true,
        }
    }
}
*/

impl<D> From<D> for Shape<D>
    where D: Dimension
{
    fn from(d: D) -> Self {
        Shape {
            dim: d,
            is_c: true,
        }
    }
}

impl From<Ix> for Shape<[Ix; 1]>
{
    fn from(ix: Ix) -> Self {
        Shape {
            dim: [ix],
            is_c: true,
        }
    }
}

impl From<(Ix, Ix)> for Shape<[Ix; 2]>
{
    fn from(ix: (Ix, Ix)) -> Self {
        Shape {
            dim: [ix.0, ix.1],
            is_c: true,
        }
    }
}

impl<T, D> From<T> for StrideShape<D>
    where D: Dimension,
          T: IntoShape<Dim=D>,
{
    fn from(value: T) -> Self {
        let shape = value.into_shape();
        let d = shape.dim;
        let st = if shape.is_c { d.default_strides() } else { d.fortran_strides() };
        StrideShape {
            strides: st,
            dim: d,
            custom: false,
        }
    }
}

/*
impl<D> From<Shape<D>> for StrideShape<D>
    where D: Dimension
{
    fn from(shape: Shape<D>) -> Self {
        let d = shape.dim;
        let st = if shape.is_c { d.default_strides() } else { d.fortran_strides() };
        StrideShape {
            strides: st,
            dim: d,
            custom: false,
        }
    }
}
*/

impl<T> ShapeBuilder for T
    where T: IntoDimension
{
    type Dim = T::Dim;
    type Strides = T;
    fn f(self) -> Shape<Self::Dim> { self.set_f(true) }
    fn set_f(self, is_f: bool) -> Shape<Self::Dim> {
        self.into_shape().set_f(is_f)
    }
    fn strides(self, st: T) -> StrideShape<Self::Dim> {
        self.into_shape().strides(st.into_dimension())
    }
}

impl<D> ShapeBuilder for Shape<D>
    where D: Dimension
{
    type Dim = D;
    type Strides = D;
    fn f(self) -> Self { self.set_f(true) }
    fn set_f(mut self, is_f: bool) -> Self {
        self.is_c = !is_f;
        self
    }
    fn strides(self, st: D) -> StrideShape<D> {
        StrideShape {
            dim: self.dim,
            strides: st,
            custom: true,
        }
    }
}

impl<D> Shape<D>
    where D: Dimension,
{
    // Return a reference to the dimension
    //pub fn dimension(&self) -> &D { &self.dim }
    /// Return the size of the shape in number of elements
    pub fn size(&self) -> usize { self.dim.size() }
}
<|endoftext|>


<commit_before>/* Cymbalum, Molecular Simulation in Rust - Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 */
//! Complex type
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::f64;

#[derive(Debug, Clone, Copy, PartialEq, Default)]
/// Complex number, only implemented for f64 real and imag parts
pub struct Complex {
    /// Real part of the complex
    real: f64,
    /// Imaginary part of the complex
    imag: f64,
}

impl Complex {
    /// Create a new `Complex` from a norm `r` and a phase `phi` in radians.
    pub fn polar(r: f64, phi: f64) -> Complex {
        Complex{
            real: r * f64::cos(phi),
            imag: r * f64::sin(phi)
        }
    }

    /// Create a complex from cartesian coordinates
    pub fn cartesian(x: f64, y: f64) -> Complex {
        Complex{
            real: x,
            imag: y,
        }
    }

    /// Get the real part of the complex
    #[inline]
    pub fn real(&self) -> f64 {
        self.real
    }

    /// Get the imaginary part of the complex
    #[inline]
    pub fn imag(&self) -> f64 {
        self.imag
    }

    /// Get the phase of the complex in the [-π, π) interval
    #[inline]
    pub fn phase(&self) -> f64 {
        f64::atan2(self.imag, self.real)
    }

    /// Get the norm of the complex
    #[inline]
    pub fn norm(&self) -> f64 {
        f64::sqrt(self.real * self.real + self.imag * self.imag)
    }
}

impl Add<Complex> for Complex {
    type Output = Complex;
    fn add(self, other: Complex) -> Complex {
        let x = self.real() + other.real();
        let y = self.imag() + other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Sub<Complex> for Complex {
    type Output = Complex;
    fn sub(self, other: Complex) -> Complex {
        let x = self.real() - other.real();
        let y = self.imag() - other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Neg for Complex {
    type Output = Complex;
    fn neg(self) -> Complex {
        Complex{
            real: -self.real,
            imag: -self.imag,
        }
    }
}

impl Mul<Complex> for Complex {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        let norm = self.norm() * other.norm();
        let phase = self.phase() + other.phase();
        Complex::polar(norm, phase)
    }
}

impl Mul<f64> for Complex {
    type Output = Complex;
    fn mul(self, other: f64) -> Complex {
        let norm = self.norm() * other;
        let phase = self.phase();
        Complex::polar(norm, phase)
    }
}

impl Mul<Complex> for f64 {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        let norm = self * other.norm();
        let phase = other.phase();
        Complex::polar(norm, phase)
    }
}

impl Div<Complex> for Complex {
    type Output = Complex;
    fn div(self, other: Complex) -> Complex {
        let norm = self.norm() / other.norm();
        let phase = self.phase() - other.phase();
        Complex::polar(norm, phase)
    }
}

impl Div<f64> for Complex {
    type Output = Complex;
    fn div(self, other: f64) -> Complex {
        let norm = self.norm() / other;
        let phase = self.phase();
        Complex::polar(norm, phase)
    }
}

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

    #[test]
    fn norm() {
        let c = Complex::polar(3.0, 5.0);
        assert_approx_eq!(c.norm(), 3.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_approx_eq!(c.norm(), 3.0);
    }

    #[test]
    fn phase() {
        // Phase is between 0 and 2π
        for &phase in &[-consts::PI, -3.1, -1.5, 0.0, 0.1, 2.0, 3.1] {
            let c = Complex::polar(1.0, phase);
            assert_approx_eq!(c.phase(), phase);
        }

        let c = Complex::polar(1.0, -8.0);
        assert_approx_eq!(c.phase(), -8.0 + 2.0 * consts::PI);

        let c = Complex::polar(1.0, 12.0);
        assert_approx_eq!(c.phase(), 12.0 - 4.0 * consts::PI);

        let c = Complex::polar(1.0, consts::PI);
        assert_eq!(c.phase(), consts::PI);
        let c = Complex::polar(1.0, -consts::PI);
        assert_eq!(c.phase(), -consts::PI);

        let c = Complex::polar(3.0, 0.0);
        assert_eq!(c.phase(), 0.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_eq!(c.phase(), -consts::PI);
    }

    #[test]
    fn cartesian() {
        let c = Complex::polar(1.0, 0.0);
        assert_approx_eq!(c.real(), 1.0);
        assert_approx_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::PI);
        assert_approx_eq!(c.real(), -1.0);
        assert_approx_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_2);
        assert_approx_eq!(c.real(), 0.0);
        assert_approx_eq!(c.imag(), 1.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_4);
        assert_approx_eq!(c.real(), consts::FRAC_1_SQRT_2);
        assert_approx_eq!(c.imag(), consts::FRAC_1_SQRT_2);

        let c = Complex::cartesian(consts::FRAC_1_SQRT_2, consts::FRAC_1_SQRT_2);
        assert_approx_eq!(c.norm(), 1.0);
        assert_approx_eq!(c.phase(), consts::FRAC_PI_4);
    }

    #[test]
    fn add() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a + b;

        assert_eq!(c.real(), a.real() + b.real());
        assert_eq!(c.imag(), a.imag() + b.imag());
    }

    #[test]
    fn sub() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a - b;

        assert_eq!(c.real(), a.real() - b.real());
        assert_eq!(c.imag(), a.imag() - b.imag());
    }

    #[test]
    fn neg() {
        let a = Complex::polar(2.0, 0.2);
        let c = -a;

        assert_approx_eq!(c.norm(), a.norm());
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);

        assert_approx_eq!(c.real(), - a.real());
        assert_approx_eq!(c.imag(), - a.imag());
    }

    #[test]
    fn mul() {
        let a = Complex::polar(2.0, 1.4);
        let b = Complex::polar(1.0, 0.5);
        let c = a * b;

        assert_eq!(c.norm(), a.norm() * b.norm());
        assert_eq!(c.phase(), a.phase() + b.phase());

        let c = 3.0 * a;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = a * 3.0;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = -2.0 * a;
        assert_eq!(c.norm(), 2.0 * a.norm());
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);
    }

    #[test]
    fn div() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a / b;

        assert_eq!(c.norm(), a.norm() / b.norm());
        assert_eq!(c.phase(), a.phase() - b.phase());

        let c = a / 3.0;
        assert_eq!(c.norm(), a.norm()/3.0);
        assert_approx_eq!(c.phase(), a.phase());

        let c = a / (-2.0);
        assert_eq!(c.norm(), a.norm()/2.0);
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);
    }
}
<commit_msg>Faster multiplication and division for complex<commit_after>/* Cymbalum, Molecular Simulation in Rust - Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 */
//! Complex type
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::f64;

#[derive(Debug, Clone, Copy, PartialEq, Default)]
/// Complex number, only implemented for f64 real and imag parts
pub struct Complex {
    /// Real part of the complex
    real: f64,
    /// Imaginary part of the complex
    imag: f64,
}

impl Complex {
    /// Create a new `Complex` from a norm `r` and a phase `phi` in radians.
    pub fn polar(r: f64, phi: f64) -> Complex {
        Complex{
            real: r * f64::cos(phi),
            imag: r * f64::sin(phi)
        }
    }

    /// Create a complex from cartesian coordinates
    pub fn cartesian(x: f64, y: f64) -> Complex {
        Complex{
            real: x,
            imag: y,
        }
    }

    /// Get the real part of the complex
    #[inline]
    pub fn real(&self) -> f64 {
        self.real
    }

    /// Get the imaginary part of the complex
    #[inline]
    pub fn imag(&self) -> f64 {
        self.imag
    }

    /// Get the phase of the complex in the [-π, π) interval
    #[inline]
    pub fn phase(&self) -> f64 {
        f64::atan2(self.imag, self.real)
    }

    /// Get the norm of the complex
    #[inline]
    pub fn norm(&self) -> f64 {
        f64::sqrt(self.norm2())
    }

    /// Get the square of the norm if this complex
    #[inline]
    pub fn norm2(&self) -> f64 {
        self.real * self.real + self.imag * self.imag
    }
}

impl Add<Complex> for Complex {
    type Output = Complex;
    fn add(self, other: Complex) -> Complex {
        let x = self.real() + other.real();
        let y = self.imag() + other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Sub<Complex> for Complex {
    type Output = Complex;
    fn sub(self, other: Complex) -> Complex {
        let x = self.real() - other.real();
        let y = self.imag() - other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Neg for Complex {
    type Output = Complex;
    fn neg(self) -> Complex {
        Complex{
            real: -self.real,
            imag: -self.imag,
        }
    }
}

impl Mul<Complex> for Complex {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        let x = self.real() * other.real() - self.imag() * other.imag();
        let y = self.real() * other.imag() + self.imag() * other.real();
        Complex::cartesian(x, y)
    }
}

impl Mul<f64> for Complex {
    type Output = Complex;
    fn mul(self, other: f64) -> Complex {
        Complex::cartesian(self.real() * other, self.imag() * other)
    }
}

impl Mul<Complex> for f64 {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        Complex::cartesian(self * other.real(), self * other.imag())
    }
}

impl Div<Complex> for Complex {
    type Output = Complex;
    fn div(self, other: Complex) -> Complex {
        let r = other.norm2();
        let x = self.real() * other.real() + self.imag() * other.imag();
        let y = - self.real() * other.imag() + self.imag() * other.real();

        Complex::cartesian(x / r, y / r)
    }
}

impl Div<f64> for Complex {
    type Output = Complex;
    fn div(self, other: f64) -> Complex {
        let norm = self.norm() / other;
        let phase = self.phase();
        Complex::polar(norm, phase)
    }
}

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

    #[test]
    fn norm() {
        let c = Complex::polar(3.0, 5.0);
        assert_approx_eq!(c.norm(), 3.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_approx_eq!(c.norm(), 3.0);
    }

    #[test]
    fn phase() {
        // Phase is between 0 and 2π
        for &phase in &[-consts::PI, -3.1, -1.5, 0.0, 0.1, 2.0, 3.1] {
            let c = Complex::polar(1.0, phase);
            assert_approx_eq!(c.phase(), phase);
        }

        let c = Complex::polar(1.0, -8.0);
        assert_approx_eq!(c.phase(), -8.0 + 2.0 * consts::PI);

        let c = Complex::polar(1.0, 12.0);
        assert_approx_eq!(c.phase(), 12.0 - 4.0 * consts::PI);

        let c = Complex::polar(1.0, consts::PI);
        assert_eq!(c.phase(), consts::PI);
        let c = Complex::polar(1.0, -consts::PI);
        assert_eq!(c.phase(), -consts::PI);

        let c = Complex::polar(3.0, 0.0);
        assert_eq!(c.phase(), 0.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_eq!(c.phase(), -consts::PI);
    }

    #[test]
    fn cartesian() {
        let c = Complex::polar(1.0, 0.0);
        assert_approx_eq!(c.real(), 1.0);
        assert_approx_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::PI);
        assert_approx_eq!(c.real(), -1.0);
        assert_approx_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_2);
        assert_approx_eq!(c.real(), 0.0);
        assert_approx_eq!(c.imag(), 1.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_4);
        assert_approx_eq!(c.real(), consts::FRAC_1_SQRT_2);
        assert_approx_eq!(c.imag(), consts::FRAC_1_SQRT_2);

        let c = Complex::cartesian(consts::FRAC_1_SQRT_2, consts::FRAC_1_SQRT_2);
        assert_approx_eq!(c.norm(), 1.0);
        assert_approx_eq!(c.phase(), consts::FRAC_PI_4);
    }

    #[test]
    fn add() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a + b;

        assert_eq!(c.real(), a.real() + b.real());
        assert_eq!(c.imag(), a.imag() + b.imag());
    }

    #[test]
    fn sub() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a - b;

        assert_eq!(c.real(), a.real() - b.real());
        assert_eq!(c.imag(), a.imag() - b.imag());
    }

    #[test]
    fn neg() {
        let a = Complex::polar(2.0, 0.2);
        let c = -a;

        assert_approx_eq!(c.norm(), a.norm());
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);

        assert_approx_eq!(c.real(), - a.real());
        assert_approx_eq!(c.imag(), - a.imag());
    }

    #[test]
    fn mul() {
        let a = Complex::polar(2.0, 1.4);
        let b = Complex::polar(1.0, 0.5);
        let c = a * b;

        assert_eq!(c.norm(), a.norm() * b.norm());
        assert_eq!(c.phase(), a.phase() + b.phase());

        let c = 3.0 * a;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = a * 3.0;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = -2.0 * a;
        assert_eq!(c.norm(), 2.0 * a.norm());
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);
    }

    #[test]
    fn div() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a / b;

        assert_eq!(c.norm(), a.norm() / b.norm());
        assert_eq!(c.phase(), a.phase() - b.phase());

        let c = a / 3.0;
        assert_eq!(c.norm(), a.norm()/3.0);
        assert_approx_eq!(c.phase(), a.phase());

        let c = a / (-2.0);
        assert_eq!(c.norm(), a.norm()/2.0);
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016-2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms.
use ctypes::{c_int, c_void};
use shared::basetsd::SIZE_T;
use shared::guiddef::CLSID;
use shared::minwindef::{DWORD, FILETIME, ULONG};
use shared::wtypesbase::LPOLESTR;
use um::unknwnbase::{IUnknown, IUnknownVtbl};
use um::winnt::{HRESULT, LARGE_INTEGER, ULARGE_INTEGER};
RIDL!{#[uuid(0x00000002, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)]
interface IMalloc(IMallocVtbl): IUnknown(IUnknownVtbl) {
    fn Alloc(cb: SIZE_T) -> *mut c_void,
    fn Realloc(pv: *mut c_void, cb: SIZE_T) -> *mut c_void,
    fn Free(pv: *mut c_void) -> (),
    fn GetSize(pv: *mut c_void) -> SIZE_T,
    fn DidAlloc(pv: *mut c_void) -> c_int,
    fn HeapMinimize() -> ()
}}
pub type LPMALLOC = *mut IMalloc;
STRUCT!{struct STATSTG {
    pwcsName: LPOLESTR,
    type_: DWORD,
    cbSize: ULARGE_INTEGER,
    mtime: FILETIME,
    ctime: FILETIME,
    atime: FILETIME,
    grfMode: DWORD,
    grfLocksSupported: DWORD,
    clsid: CLSID,
    grfStateBits: DWORD,
    reserved: DWORD,
}}
//1945
pub type IEnumString = IUnknown; // TODO
//2075
RIDL!(#[uuid(0x0c733a30, 0x2a1c, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d)]
interface ISequentialStream(ISequentialStreamVtbl): IUnknown(IUnknownVtbl) {
    fn Read(pv: *mut c_void, cb: ULONG, pcbRead: *mut ULONG) -> HRESULT,
    fn Write(pv: *const c_void, cb: ULONG, pcbWritten: *mut ULONG) -> HRESULT
}
);
ENUM!{enum STGTY {
    STGTY_STORAGE = 1,
    STGTY_STREAM = 2,
    STGTY_LOCKBYTES = 3,
    STGTY_PROPERTY = 4,
}}
ENUM!{enum STREAM_SEEK {
    STREAM_SEEK_SET = 0,
    STREAM_SEEK_CUR = 1,
    STREAM_SEEK_END = 2,
}}
ENUM!{enum LOCKTYPE {
    LOCK_WRITE = 1,
    LOCK_EXCLUSIVE = 2,
    LOCK_ONLYONCE = 4,
}}
//2255
RIDL!(#[uuid(0x0000000c, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)]
interface IStream(IStreamVtbl): ISequentialStream(ISequentialStreamVtbl) {
    fn Seek(
        dlibMove: LARGE_INTEGER, dwOrigin: DWORD,
        plibNewPosition: *mut ULARGE_INTEGER
    ) -> HRESULT,
    fn SetSize(libNewSize: ULARGE_INTEGER) -> HRESULT,
    fn CopyTo(
        pstm: *mut IStream, cb: ULARGE_INTEGER, pcbRead: *mut ULARGE_INTEGER,
        pcbWritten: *mut ULARGE_INTEGER
    ) -> HRESULT,
    fn Commit(grfCommitFlags: DWORD) -> HRESULT,
    fn Revert() -> HRESULT,
    fn LockRegion(
        libOffset: ULARGE_INTEGER, cb: ULARGE_INTEGER, dwLockType: DWORD
    ) -> HRESULT,
    fn UnlockRegion(
        libOffset: ULARGE_INTEGER, cb: ULARGE_INTEGER, dwLockType: DWORD
    ) -> HRESULT,
    fn Stat(pstatstg: *mut STATSTG, grfStatFlag: DWORD) -> HRESULT,
    fn Clone(ppstm: *mut *mut IStream) -> HRESULT
}
);
pub type LPSTREAM = *mut IStream;
ENUM!{enum APTTYPEQUALIFIER {
    APTTYPEQUALIFIER_NONE = 0,
    APTTYPEQUALIFIER_IMPLICIT_MTA = 1,
    APTTYPEQUALIFIER_NA_ON_MTA = 2,
    APTTYPEQUALIFIER_NA_ON_STA = 3,
    APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA = 4,
    APTTYPEQUALIFIER_NA_ON_MAINSTA = 5,
    APTTYPEQUALIFIER_APPLICATION_STA= 6,
}}
ENUM!{enum APTTYPE {
    APTTYPE_CURRENT = -1i32 as u32,
    APTTYPE_STA = 0,
    APTTYPE_MTA = 1,
    APTTYPE_NA = 2,
    APTTYPE_MAINSTA = 3,
}}
<commit_msg>add IEnumUnknown (#407)<commit_after>// Copyright © 2016-2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms.
use ctypes::{c_int, c_void};
use shared::basetsd::SIZE_T;
use shared::guiddef::CLSID;
use shared::minwindef::{DWORD, FILETIME, ULONG};
use shared::wtypesbase::LPOLESTR;
use um::unknwnbase::{IUnknown, IUnknownVtbl};
use um::winnt::{HRESULT, LARGE_INTEGER, ULARGE_INTEGER};
RIDL!{#[uuid(0x00000002, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)]
interface IMalloc(IMallocVtbl): IUnknown(IUnknownVtbl) {
    fn Alloc(cb: SIZE_T) -> *mut c_void,
    fn Realloc(pv: *mut c_void, cb: SIZE_T) -> *mut c_void,
    fn Free(pv: *mut c_void) -> (),
    fn GetSize(pv: *mut c_void) -> SIZE_T,
    fn DidAlloc(pv: *mut c_void) -> c_int,
    fn HeapMinimize() -> ()
}}
pub type LPMALLOC = *mut IMalloc;
RIDL!{#[uuid(0x00000100, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)]
interface IEnumUnknown(IEnumUnknownVtbl): IUnknown(IUnknownVtbl) {
    fn Next(
        celt: ULONG,
        rgelt: *mut *mut IUnknown,
        pceltFetched: *mut ULONG
    ) -> HRESULT,
    fn Skip(celt: ULONG) -> HRESULT,
    fn Reset() -> HRESULT,
    fn Clone(ppenum: *mut *mut IEnumUnknown) -> HRESULT
}}
STRUCT!{struct STATSTG {
    pwcsName: LPOLESTR,
    type_: DWORD,
    cbSize: ULARGE_INTEGER,
    mtime: FILETIME,
    ctime: FILETIME,
    atime: FILETIME,
    grfMode: DWORD,
    grfLocksSupported: DWORD,
    clsid: CLSID,
    grfStateBits: DWORD,
    reserved: DWORD,
}}
//1945
pub type IEnumString = IUnknown; // TODO
//2075
RIDL!(#[uuid(0x0c733a30, 0x2a1c, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d)]
interface ISequentialStream(ISequentialStreamVtbl): IUnknown(IUnknownVtbl) {
    fn Read(pv: *mut c_void, cb: ULONG, pcbRead: *mut ULONG) -> HRESULT,
    fn Write(pv: *const c_void, cb: ULONG, pcbWritten: *mut ULONG) -> HRESULT
}
);
ENUM!{enum STGTY {
    STGTY_STORAGE = 1,
    STGTY_STREAM = 2,
    STGTY_LOCKBYTES = 3,
    STGTY_PROPERTY = 4,
}}
ENUM!{enum STREAM_SEEK {
    STREAM_SEEK_SET = 0,
    STREAM_SEEK_CUR = 1,
    STREAM_SEEK_END = 2,
}}
ENUM!{enum LOCKTYPE {
    LOCK_WRITE = 1,
    LOCK_EXCLUSIVE = 2,
    LOCK_ONLYONCE = 4,
}}
//2255
RIDL!(#[uuid(0x0000000c, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)]
interface IStream(IStreamVtbl): ISequentialStream(ISequentialStreamVtbl) {
    fn Seek(
        dlibMove: LARGE_INTEGER, dwOrigin: DWORD,
        plibNewPosition: *mut ULARGE_INTEGER
    ) -> HRESULT,
    fn SetSize(libNewSize: ULARGE_INTEGER) -> HRESULT,
    fn CopyTo(
        pstm: *mut IStream, cb: ULARGE_INTEGER, pcbRead: *mut ULARGE_INTEGER,
        pcbWritten: *mut ULARGE_INTEGER
    ) -> HRESULT,
    fn Commit(grfCommitFlags: DWORD) -> HRESULT,
    fn Revert() -> HRESULT,
    fn LockRegion(
        libOffset: ULARGE_INTEGER, cb: ULARGE_INTEGER, dwLockType: DWORD
    ) -> HRESULT,
    fn UnlockRegion(
        libOffset: ULARGE_INTEGER, cb: ULARGE_INTEGER, dwLockType: DWORD
    ) -> HRESULT,
    fn Stat(pstatstg: *mut STATSTG, grfStatFlag: DWORD) -> HRESULT,
    fn Clone(ppstm: *mut *mut IStream) -> HRESULT
}
);
pub type LPSTREAM = *mut IStream;
ENUM!{enum APTTYPEQUALIFIER {
    APTTYPEQUALIFIER_NONE = 0,
    APTTYPEQUALIFIER_IMPLICIT_MTA = 1,
    APTTYPEQUALIFIER_NA_ON_MTA = 2,
    APTTYPEQUALIFIER_NA_ON_STA = 3,
    APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA = 4,
    APTTYPEQUALIFIER_NA_ON_MAINSTA = 5,
    APTTYPEQUALIFIER_APPLICATION_STA= 6,
}}
ENUM!{enum APTTYPE {
    APTTYPE_CURRENT = -1i32 as u32,
    APTTYPE_STA = 0,
    APTTYPE_MTA = 1,
    APTTYPE_NA = 2,
    APTTYPE_MAINSTA = 3,
}}
<|endoftext|>


<commit_before>//! Askama implements a type-safe compiler for Jinja-like templates.
//! It lets you write templates in a Jinja-like syntax,
//! which are linked to a `struct` defining the template context.
//! This is done using a custom derive implementation (implemented
//! in [`askama_derive`](https://crates.io/crates/askama_derive)).
//!
//! # Example template
//!
//! ```text
//! {% extends "layout.html" %}
//! {% block body %}
//!   <ul>
//!     {% for user in users %}
//!       <li><a href="{{ user.url }}">{{ user.username }}</a></li>
//!     {% endfor %}
//!   </ul>
//! {% endblock %}
//! ```
//!
//! # Feature highlights
//!
//! * Construct templates using a familiar, easy-to-use syntax
//! * Benefit from the safety provided by Rust's type system
//! * Template code is compiled into your crate for optimal performance
//! * Templates only convert your data as needed
//! * Templates can access your Rust types directly, according to Rust's
//!   privacy rules
//! * Debugging features to assist you in template development
//! * Templates must be valid UTF-8 and produce UTF-8 when rendered
//! * Works on stable Rust
//!
//! # Creating Askama templates
//!
//! An Askama template is just a text file, in the UTF-8 encoding.
//! It can be used to generate any kind of text-based format.
//! You can use whatever extension you like.
//!
//! A template consists of **text contents**, which are passed through as-is,
//! **expressions**, which get replaced with content while being rendered, and
//! **tags**, which control the template's logic.
//! The template syntax is very similar to [Jinja](http://jinja.pocoo.org/),
//! as well as Jinja-derivatives like [Twig](http://twig.sensiolabs.org/) or
//! [Tera](https://github.com/Keats/tera).
//!
//! ## Variables
//!
//! Template variables are defined by the template context linked to the
//! template by deriving a `struct`'s implementation for `Template` from
//! a template file's contents.
//! You can use a dot (`.`) to get a variable's attributes.
//! Reading from variables is subject to the usual borrowing policies.
//! For example, `{{ name }}` will get the ``name`` field from the template
//! context,
//! while `{{ user.name }}` will get the ``name`` field of the ``user``
//! field from the template context.
//!
//! ## Filters
//!
//! Values such as those obtained from variables can be post-processed
//! using **filters**.
//! Filters are applied to values using the pipe symbol (`|`) and may
//! have optional extra arguments in parentheses.
//! Filters can be chained, in which case the output from one filter
//! is passed to the next.
//!
//! For example, `{{ "{:?}"|format(name|escape) }}` will escape HTML
//! characters from the value obtained by accessing the `name` field,
//! and print the resulting string as a Rust literal.
//!
//! Consult the [filters module documentation](filters/index.html) for a list
//! of available filters. User-defined filters are currently not supported.
//!
//! ## Whitespace control
//!
//! Askama preserves all whitespace in template code by default,
//! except that final trailing newline characters are suppressed.
//! However, whitespace before and after expression and block delimiters
//! can be suppressed by writing a minus sign directly following a
//! start delimiter or leading into an end delimiter.
//! Askama considers all tabs, spaces, newlines and carriage returns to be
//! whitespace.
//!
//! ## Template inheritance
//!
//! Template inheritance allows you to build a base template with common
//! elements that can then be shared by all inheriting templates.
//! A base template defines **blocks** that child templates can then override.
//!
//! ### Base template
//!
//! ```text
//! <!DOCTYPE html>
//! <html lang="en">
//!   <head>
//!     <title>{{ block title %}{{ title }}{% endblock %} - My Site</title>
//!     {% block head %}{% endblock %}
//!   </head>
//!   <body>
//!     <div id="content">
//!       {% block content %}{% endblock %}
//!     </div>
//!   </body>
//! </html>
//! ```
//!
//! The `block` tags define three blocks that can be filled in by child
//! templates. The base template defines a default version of the block.
//! A base template must define one or more blocks in order to be enable
//! inheritance.
//!
//! ### Child template
//!
//! Here's an example child template:
//!
//! ```text
//! {% extends "base.html" %}
//!
//! {% block title %}Index{% endblock %}
//!
//! {% block head %}
//!   <style>
//!   </style>
//! {% endblock %}
//!
//! {% block content %}
//!   <h1>Index</h1>
//!   <p>Hello, world!</p>
//! {% endblock %}
//! ```
//!
//! The `extends` tag tells the code generator that this template inherits
//! from another template. It will search for the base template relative to
//! itself before looking relative to the template base directory. It will
//! render the top-level content from the base template, and substitute
//! blocks from the base template with those from the child template. The
//! inheriting template context `struct` must have a field called `_parent` of
//! the type used as the base template context. Blocks can refer to the context
//! of both parent and child template.
//!
//! Note that, if the base template lives in another module than the child
//! template, the child template's module should import all symbols from the
//! base template's module in order for it to find the trait definition that
//! supports the inheritance mechanism.
//!
//! ## HTML escaping
//!
//! Askama does not yet support automatic escaping. Care must be taken to
//! escape content that may contain HTML control characters. You can use
//! the `escape` filter (or its `e` alias) to escape data for use in HTML.
//!
//! ## Control structures
//!
//! ### For
//!
//! Loop over each item in an iterator. For example:
//!
//! ```text
//! <h1>Users</h1>
//! <ul>
//! {% for user in users %}
//!   <li>{{ user.name|e }}</li>
//! {% endfor %}
//! </ul>
//! ```
//!
//! Inside for-loop blocks, some useful variables are accessible:
//!
//! * *loop.index*: current loop iteration (starting from 1)
//! * *loop.index0*: current loop iteration (starting from 0)
//!
//! ### If
//!
//! The *if* statement is used as you might expect:
//!
//! ```text
//! {% if users.len() == 0 %}
//!   No users
//! {% else if users.len() == 1 %}
//!   1 user
//! {% else %}
//!   {{ users.len() }} users
//! {% endif %}
//! ```
//!
//! ## Expressions
//!
//! Askama supports string literals (`"foo"`) and integer literals (`1`).
//! It supports almost all binary operators that Rust supports,
//! including arithmetic, comparison and logic operators.
//! The same precedence order as Rust uses is applied.
//! Expressions can be grouped using parentheses.

#![allow(unused_imports)]
#[macro_use]
extern crate askama_derive;

use std::env;
use std::fs::{self, DirEntry};
use std::io;
use std::path::{Path, PathBuf};

/// Main `Template` trait; implementations are generally derived
pub trait Template {
    /// Renders the template to the given `writer` buffer
    fn render_to(&self, writer: &mut std::fmt::Write);
    /// Helper method which allocates a new `String` and renders into it
    fn render(&self) -> String {
        let mut buf = String::new();
        self.render_to(&mut buf);
        buf
    }
}

pub mod filters;
pub use askama_derive::*;

// Duplicates askama_derive::path::template_dir()
fn template_dir() -> PathBuf {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    path.push("templates");
    path
}

fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {
    if dir.is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            let path = entry.path();
            if path.is_dir() {
                try!(visit_dirs(&path, cb));
            } else {
                cb(&entry);
            }
        }
    }
    Ok(())
}

/// Build script helper to rebuild crates if contained templates have changed
///
/// Iterates over all files in the template dir (`templates` in
/// `CARGO_MANIFEST_DIR`) and writes a `cargo:rerun-if-changed=` line for each
/// of them to stdout.
///
/// This helper method can be used in build scripts (`build.rs`) in crates
/// that have templates, to make sure the crate gets rebuilt when template
/// source code changes.
pub fn rerun_if_templates_changed() {
    visit_dirs(&template_dir(), &|e: &DirEntry| {
        println!("cargo:rerun-if-changed={}", e.path().to_str().unwrap());
    }).unwrap();
}
<commit_msg>Add some documentation about includes<commit_after>//! Askama implements a type-safe compiler for Jinja-like templates.
//! It lets you write templates in a Jinja-like syntax,
//! which are linked to a `struct` defining the template context.
//! This is done using a custom derive implementation (implemented
//! in [`askama_derive`](https://crates.io/crates/askama_derive)).
//!
//! # Example template
//!
//! ```text
//! {% extends "layout.html" %}
//! {% block body %}
//!   <ul>
//!     {% for user in users %}
//!       <li><a href="{{ user.url }}">{{ user.username }}</a></li>
//!     {% endfor %}
//!   </ul>
//! {% endblock %}
//! ```
//!
//! # Feature highlights
//!
//! * Construct templates using a familiar, easy-to-use syntax
//! * Benefit from the safety provided by Rust's type system
//! * Template code is compiled into your crate for optimal performance
//! * Templates only convert your data as needed
//! * Templates can access your Rust types directly, according to Rust's
//!   privacy rules
//! * Debugging features to assist you in template development
//! * Templates must be valid UTF-8 and produce UTF-8 when rendered
//! * Works on stable Rust
//!
//! # Creating Askama templates
//!
//! An Askama template is just a text file, in the UTF-8 encoding.
//! It can be used to generate any kind of text-based format.
//! You can use whatever extension you like.
//!
//! A template consists of **text contents**, which are passed through as-is,
//! **expressions**, which get replaced with content while being rendered, and
//! **tags**, which control the template's logic.
//! The template syntax is very similar to [Jinja](http://jinja.pocoo.org/),
//! as well as Jinja-derivatives like [Twig](http://twig.sensiolabs.org/) or
//! [Tera](https://github.com/Keats/tera).
//!
//! ## Variables
//!
//! Template variables are defined by the template context linked to the
//! template by deriving a `struct`'s implementation for `Template` from
//! a template file's contents.
//! You can use a dot (`.`) to get a variable's attributes.
//! Reading from variables is subject to the usual borrowing policies.
//! For example, `{{ name }}` will get the ``name`` field from the template
//! context,
//! while `{{ user.name }}` will get the ``name`` field of the ``user``
//! field from the template context.
//!
//! ## Filters
//!
//! Values such as those obtained from variables can be post-processed
//! using **filters**.
//! Filters are applied to values using the pipe symbol (`|`) and may
//! have optional extra arguments in parentheses.
//! Filters can be chained, in which case the output from one filter
//! is passed to the next.
//!
//! For example, `{{ "{:?}"|format(name|escape) }}` will escape HTML
//! characters from the value obtained by accessing the `name` field,
//! and print the resulting string as a Rust literal.
//!
//! Consult the [filters module documentation](filters/index.html) for a list
//! of available filters. User-defined filters are currently not supported.
//!
//! ## Whitespace control
//!
//! Askama preserves all whitespace in template code by default,
//! except that final trailing newline characters are suppressed.
//! However, whitespace before and after expression and block delimiters
//! can be suppressed by writing a minus sign directly following a
//! start delimiter or leading into an end delimiter.
//! Askama considers all tabs, spaces, newlines and carriage returns to be
//! whitespace.
//!
//! ## Template inheritance
//!
//! Template inheritance allows you to build a base template with common
//! elements that can then be shared by all inheriting templates.
//! A base template defines **blocks** that child templates can then override.
//!
//! ### Base template
//!
//! ```text
//! <!DOCTYPE html>
//! <html lang="en">
//!   <head>
//!     <title>{{ block title %}{{ title }}{% endblock %} - My Site</title>
//!     {% block head %}{% endblock %}
//!   </head>
//!   <body>
//!     <div id="content">
//!       {% block content %}{% endblock %}
//!     </div>
//!   </body>
//! </html>
//! ```
//!
//! The `block` tags define three blocks that can be filled in by child
//! templates. The base template defines a default version of the block.
//! A base template must define one or more blocks in order to be enable
//! inheritance.
//!
//! ### Child template
//!
//! Here's an example child template:
//!
//! ```text
//! {% extends "base.html" %}
//!
//! {% block title %}Index{% endblock %}
//!
//! {% block head %}
//!   <style>
//!   </style>
//! {% endblock %}
//!
//! {% block content %}
//!   <h1>Index</h1>
//!   <p>Hello, world!</p>
//! {% endblock %}
//! ```
//!
//! The `extends` tag tells the code generator that this template inherits
//! from another template. It will search for the base template relative to
//! itself before looking relative to the template base directory. It will
//! render the top-level content from the base template, and substitute
//! blocks from the base template with those from the child template. The
//! inheriting template context `struct` must have a field called `_parent` of
//! the type used as the base template context. Blocks can refer to the context
//! of both parent and child template.
//!
//! Note that, if the base template lives in another module than the child
//! template, the child template's module should import all symbols from the
//! base template's module in order for it to find the trait definition that
//! supports the inheritance mechanism.
//!
//! ## HTML escaping
//!
//! Askama does not yet support automatic escaping. Care must be taken to
//! escape content that may contain HTML control characters. You can use
//! the `escape` filter (or its `e` alias) to escape data for use in HTML.
//!
//! ## Control structures
//!
//! ### For
//!
//! Loop over each item in an iterator. For example:
//!
//! ```text
//! <h1>Users</h1>
//! <ul>
//! {% for user in users %}
//!   <li>{{ user.name|e }}</li>
//! {% endfor %}
//! </ul>
//! ```
//!
//! Inside for-loop blocks, some useful variables are accessible:
//!
//! * *loop.index*: current loop iteration (starting from 1)
//! * *loop.index0*: current loop iteration (starting from 0)
//!
//! ### If
//!
//! The *if* statement is used as you might expect:
//!
//! ```text
//! {% if users.len() == 0 %}
//!   No users
//! {% else if users.len() == 1 %}
//!   1 user
//! {% else %}
//!   {{ users.len() }} users
//! {% endif %}
//! ```
//!
//! ### Include
//!
//! The *include* statement lets you split large or repetitive blocks into
//! separate template files. Included templates get full access to the context
//! in which they're used, including local variables like those from loops:
//!
//! ```text
//! {% for i in iter %}
//!   {% include "item.html" %}
//! {% endfor %}
//! ```
//!
//! ```text
//! * Item: {{ i }}
//! ```
//!
//! The path to include must be a string literal, so that it is known at
//! compile time. You can use include within the branches of an if/else
//! block to use includes more dynamically.
//!
//! ## Expressions
//!
//! Askama supports string literals (`"foo"`) and integer literals (`1`).
//! It supports almost all binary operators that Rust supports,
//! including arithmetic, comparison and logic operators.
//! The same precedence order as Rust uses is applied.
//! Expressions can be grouped using parentheses.

#![allow(unused_imports)]
#[macro_use]
extern crate askama_derive;

use std::env;
use std::fs::{self, DirEntry};
use std::io;
use std::path::{Path, PathBuf};

/// Main `Template` trait; implementations are generally derived
pub trait Template {
    /// Renders the template to the given `writer` buffer
    fn render_to(&self, writer: &mut std::fmt::Write);
    /// Helper method which allocates a new `String` and renders into it
    fn render(&self) -> String {
        let mut buf = String::new();
        self.render_to(&mut buf);
        buf
    }
}

pub mod filters;
pub use askama_derive::*;

// Duplicates askama_derive::path::template_dir()
fn template_dir() -> PathBuf {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    path.push("templates");
    path
}

fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {
    if dir.is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            let path = entry.path();
            if path.is_dir() {
                try!(visit_dirs(&path, cb));
            } else {
                cb(&entry);
            }
        }
    }
    Ok(())
}

/// Build script helper to rebuild crates if contained templates have changed
///
/// Iterates over all files in the template dir (`templates` in
/// `CARGO_MANIFEST_DIR`) and writes a `cargo:rerun-if-changed=` line for each
/// of them to stdout.
///
/// This helper method can be used in build scripts (`build.rs`) in crates
/// that have templates, to make sure the crate gets rebuilt when template
/// source code changes.
pub fn rerun_if_templates_changed() {
    visit_dirs(&template_dir(), &|e: &DirEntry| {
        println!("cargo:rerun-if-changed={}", e.path().to_str().unwrap());
    }).unwrap();
}
<|endoftext|>


<commit_before>use super::super::{Grid, Coord};

#[derive(Clone, Copy)]
pub struct FieldShapeGrp {
    start: i32,
    end: i32,
    step: i32
}
impl Iterator for FieldShapeGrp {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        let ret = self.start;
        self.start += self.step;

        if ret < self.end {
            Some(ret)
        } else {
            None
        }
    }
}
#[derive(Clone, Copy)]
pub enum ClueLocation {
    Horizontal(i32),
    Vertical(i32)
}
pub struct FieldShape {
    pub has_clue: Grid<bool>,
    pub cell_to_groups: Grid<(i32, i32)>,
    pub group_to_cells: Vec<FieldShapeGrp>,
    pub clue_locations: Vec<ClueLocation>
}
impl FieldShape {
    fn new(has_clue: &Grid<bool>) -> FieldShape {
        let height = has_clue.height();
        let width = has_clue.width();
        let mut cell_to_groups = Grid::new(height, width, (-1, -1));
        let mut group_to_cells = vec![];
        let mut clue_locations = vec![];
        let mut current_grp_id = 0;

        // compute horizontal groups
        for y in 0..height {
            let mut start = -1;
            for x in 0..(width+1) {
                if x == width || has_clue[Coord { y: y, x: x }] {
                    if start != -1 {
                        group_to_cells.push(FieldShapeGrp {
                            start: start,
                            end: y * width + x,
                            step: 1
                        });
                        clue_locations.push(ClueLocation::Horizontal(start - 1));
                        current_grp_id += 1;
                    }
                    start = -1;
                } else {
                    if start == -1 {
                        start = y * width + x;
                    }
                    cell_to_groups[Coord { y: y, x: x }].0 = current_grp_id;
                }
            }
        }

        // compute vertical groups
        for x in 0..width {
            let mut start = -1;
            for y in 0..(height+1) {
                if y == height || has_clue[Coord { y: y, x: x }] {
                    if start != -1 {
                        group_to_cells.push(FieldShapeGrp {
                            start: start,
                            end: y * width + x,
                            step: width
                        });
                        clue_locations.push(ClueLocation::Vertical(start - width));
                        current_grp_id += 1;
                    }
                    start = -1;
                } else {
                    if start == -1 {
                        start = y * width + x;
                    }
                    cell_to_groups[Coord { y: y, x: x }].1 = current_grp_id;
                }
            }
        }

        FieldShape {
            has_clue: has_clue.clone(),
            cell_to_groups: cell_to_groups,
            group_to_cells: group_to_cells,
            clue_locations: clue_locations
        }
    }
}

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

    #[test]
    fn test_field_shape_grp() {
        {
            let mut n = 0;
            let mut sum = 0;
            let grp = FieldShapeGrp { start: 3, end: 6, step: 1 };
            for i in grp {
                n += 1;
                sum += i;
            }
            assert_eq!(n, 3);
            assert_eq!(sum, 3 + 4 + 5);
            assert_eq!(grp.start, 3);
        }
        {
            let mut n = 0;
            let mut sum = 0;
            let grp = FieldShapeGrp { start: 4, end: 16, step: 3 };
            for i in grp {
                n += 1;
                sum += i;
            }
            assert_eq!(n, 4);
            assert_eq!(sum, 4 + 7 + 10 + 13);
            assert_eq!(grp.start, 4);
        }
    }
}
<commit_msg>Kakuro: add a test<commit_after>use super::super::{Grid, Coord};

#[derive(Clone, Copy)]
pub struct FieldShapeGrp {
    start: i32,
    end: i32,
    step: i32
}
impl Iterator for FieldShapeGrp {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        let ret = self.start;
        self.start += self.step;

        if ret < self.end {
            Some(ret)
        } else {
            None
        }
    }
}
#[derive(Clone, Copy)]
pub enum ClueLocation {
    Horizontal(i32),
    Vertical(i32)
}
pub struct FieldShape {
    pub has_clue: Grid<bool>,
    pub cell_to_groups: Grid<(i32, i32)>,
    pub group_to_cells: Vec<FieldShapeGrp>,
    pub clue_locations: Vec<ClueLocation>
}
impl FieldShape {
    fn new(has_clue: &Grid<bool>) -> FieldShape {
        let height = has_clue.height();
        let width = has_clue.width();
        let mut cell_to_groups = Grid::new(height, width, (-1, -1));
        let mut group_to_cells = vec![];
        let mut clue_locations = vec![];
        let mut current_grp_id = 0;

        // compute horizontal groups
        for y in 0..height {
            let mut start = -1;
            for x in 0..(width+1) {
                if x == width || has_clue[Coord { y: y, x: x }] {
                    if start != -1 {
                        group_to_cells.push(FieldShapeGrp {
                            start: start,
                            end: y * width + x,
                            step: 1
                        });
                        clue_locations.push(ClueLocation::Horizontal(start - 1));
                        current_grp_id += 1;
                    }
                    start = -1;
                } else {
                    if start == -1 {
                        start = y * width + x;
                    }
                    cell_to_groups[Coord { y: y, x: x }].0 = current_grp_id;
                }
            }
        }

        // compute vertical groups
        for x in 0..width {
            let mut start = -1;
            for y in 0..(height+1) {
                if y == height || has_clue[Coord { y: y, x: x }] {
                    if start != -1 {
                        group_to_cells.push(FieldShapeGrp {
                            start: start,
                            end: y * width + x,
                            step: width
                        });
                        clue_locations.push(ClueLocation::Vertical(start - width));
                        current_grp_id += 1;
                    }
                    start = -1;
                } else {
                    if start == -1 {
                        start = y * width + x;
                    }
                    cell_to_groups[Coord { y: y, x: x }].1 = current_grp_id;
                }
            }
        }

        FieldShape {
            has_clue: has_clue.clone(),
            cell_to_groups: cell_to_groups,
            group_to_cells: group_to_cells,
            clue_locations: clue_locations
        }
    }
}

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

    #[test]
    fn test_field_shape_grp() {
        {
            let mut n = 0;
            let mut sum = 0;
            let grp = FieldShapeGrp { start: 3, end: 6, step: 1 };
            for i in grp {
                n += 1;
                sum += i;
            }
            assert_eq!(n, 3);
            assert_eq!(sum, 3 + 4 + 5);
            assert_eq!(grp.start, 3);
        }
        {
            let mut n = 0;
            let mut sum = 0;
            let grp = FieldShapeGrp { start: 4, end: 16, step: 3 };
            for i in grp {
                n += 1;
                sum += i;
            }
            assert_eq!(n, 4);
            assert_eq!(sum, 4 + 7 + 10 + 13);
            assert_eq!(grp.start, 4);
        }
    }

    #[test]
    fn test_field_shape() {
        {
            let clues_vec = vec![
                vec![true , true , true , true ],
                vec![true , false, false, false],
                vec![true , false, false, false],
                vec![true , true , false, false],
                vec![true , false, false, false],
                vec![true , false, false, false],
            ];
            let clues = common::vec_to_grid(&clues_vec);
            let shape = FieldShape::new(&clues);

            assert_eq!(shape.group_to_cells.len(), 9);

            let (g1, g2) = shape.cell_to_groups[Coord { y: 4, x: 1 }];
            let h1 = shape.clue_locations[g1 as usize];
            let h2 = shape.clue_locations[g2 as usize];
            assert!(match (h1, h2) {
                (ClueLocation::Horizontal(16), ClueLocation::Vertical(13))
              | (ClueLocation::Vertical(13), ClueLocation::Horizontal(16)) => true,
                _ => false
            });
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2017, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate bragi;
extern crate iron;
extern crate iron_test;
extern crate serde_json;
use super::BragiHandler;
use super::get_value;

pub fn bragi_ntfs_test(es_wrapper: ::ElasticSearchWrapper) {
    let bragi = BragiHandler::new(format!("{}/munin", es_wrapper.host()));

    let ntfs2mimir = concat!(env!("OUT_DIR"), "/../../../ntfs2mimir");
    ::launch_and_assert(
        ntfs2mimir,
        vec![
            "--input=./tests/fixtures/ntfs/".into(),
            "--dataset=dataset1".into(),
            format!("--connection-string={}", es_wrapper.host()),
        ],
        &es_wrapper,
    );

    gare_de_lyon(&bragi);
}

fn gare_de_lyon(bragi: &BragiHandler) {
    // with this query we should find only one response, a stop
    let response = bragi.get("/autocomplete?q=gare de lyon&_all_data=true");
    assert_eq!(response.len(), 1);
    let stop = response.first().unwrap();

    assert_eq!(get_value(stop, "type"), "public_transport:stop_area");
    assert_eq!(get_value(stop, "label"), "Gare de Lyon");
    assert_eq!(get_value(stop, "name"), "Gare de Lyon");
    assert_eq!(get_value(stop, "id"), "stop_area:GDL");
    assert_eq!(get_value(stop, "timezone"), "Europe/Paris");
    assert_eq!(
        stop.get("physical_modes").unwrap(),
        &json!([
            {"id": "physical_mode:Bus", "name": "Bus"},
            {"id": "physical_mode:Metro", "name": "Metro"},
            {"id": "physical_mode:RapidTransit", "name": "Rapid Transit"}
        ])
    );
    assert_eq!(
        stop.get("commercial_modes").unwrap(),
        &json!([
            {"id": "commercial_mode:Bus", "name": "Bus"},
            {"id": "commercial_mode:Metro", "name": "Metro"},
            {"id": "commercial_mode:RER", "name": "Réseau Express Régional (RER)"}
        ])
    );
    assert_eq!(
        stop.get("codes").unwrap(),
        &json!([
            {"name": "navitia1", "value": "424242"},
            {"name": "source", "value": "stop_area:GDL"},
        ])
    );
    println!("{:?}", stop);
    assert_eq!(
        stop.get("properties").unwrap(),
        &json!([
            {"key": "awesome_system", "value": "id:4242"},
        ])
    );
}
<commit_msg>remove debug message<commit_after>// Copyright © 2017, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate bragi;
extern crate iron;
extern crate iron_test;
extern crate serde_json;
use super::BragiHandler;
use super::get_value;

pub fn bragi_ntfs_test(es_wrapper: ::ElasticSearchWrapper) {
    let bragi = BragiHandler::new(format!("{}/munin", es_wrapper.host()));

    let ntfs2mimir = concat!(env!("OUT_DIR"), "/../../../ntfs2mimir");
    ::launch_and_assert(
        ntfs2mimir,
        vec![
            "--input=./tests/fixtures/ntfs/".into(),
            "--dataset=dataset1".into(),
            format!("--connection-string={}", es_wrapper.host()),
        ],
        &es_wrapper,
    );

    gare_de_lyon(&bragi);
}

fn gare_de_lyon(bragi: &BragiHandler) {
    // with this query we should find only one response, a stop
    let response = bragi.get("/autocomplete?q=gare de lyon&_all_data=true");
    assert_eq!(response.len(), 1);
    let stop = response.first().unwrap();

    assert_eq!(get_value(stop, "type"), "public_transport:stop_area");
    assert_eq!(get_value(stop, "label"), "Gare de Lyon");
    assert_eq!(get_value(stop, "name"), "Gare de Lyon");
    assert_eq!(get_value(stop, "id"), "stop_area:GDL");
    assert_eq!(get_value(stop, "timezone"), "Europe/Paris");
    assert_eq!(
        stop.get("physical_modes").unwrap(),
        &json!([
            {"id": "physical_mode:Bus", "name": "Bus"},
            {"id": "physical_mode:Metro", "name": "Metro"},
            {"id": "physical_mode:RapidTransit", "name": "Rapid Transit"}
        ])
    );
    assert_eq!(
        stop.get("commercial_modes").unwrap(),
        &json!([
            {"id": "commercial_mode:Bus", "name": "Bus"},
            {"id": "commercial_mode:Metro", "name": "Metro"},
            {"id": "commercial_mode:RER", "name": "Réseau Express Régional (RER)"}
        ])
    );
    assert_eq!(
        stop.get("codes").unwrap(),
        &json!([
            {"name": "navitia1", "value": "424242"},
            {"name": "source", "value": "stop_area:GDL"},
        ])
    );
    assert_eq!(
        stop.get("properties").unwrap(),
        &json!([
            {"key": "awesome_system", "value": "id:4242"},
        ])
    );
}
<|endoftext|>


<commit_before>use nom;
use nom::{alpha, alphanumeric, digit, multispace};
use std::str::from_utf8;

// Identifier
// IDENT := /[a-zA-Z_]\w*/g
named!(ident<&str, &str>, re_match!(r"[a-zA-Z_]\w*"));

// Whitespace
named!(whitespace, chain!(many0!(multispace), || { &b""[..] }));<commit_msg>Edit regex to allow Ruby-like identifiers<commit_after>use nom;
use nom::{alpha, alphanumeric, digit, multispace};
use std::str::from_utf8;

// Identifier
// IDENT := /[a-zA-Z_]\w*/g
named!(ident<&str, &str>, re_match!(r"[a-zA-Z_]\w*[\?\!]*"));

// Whitespace
named!(whitespace, chain!(many0!(multispace), || { &b""[..] }));
<|endoftext|>


<commit_before>use crate::common::util::*;

#[test]
fn test_rm_one_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_rm_one_file";

    at.touch(file);

    ucmd.arg(file).succeeds().no_stderr();

    assert!(!at.file_exists(file));
}

#[test]
fn test_rm_failed() {
    let (_at, mut ucmd) = at_and_ucmd!();
    let file = "test_rm_one_file";

    let result = ucmd.arg(file).fails(); // Doesn't exist

    assert!(result.stderr.contains(&format!(
        "cannot remove '{}': No such file or directory",
        file
    )));
}

#[test]
fn test_rm_multiple_files() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_rm_multiple_file_a";
    let file_b = "test_rm_multiple_file_b";

    at.touch(file_a);
    at.touch(file_b);

    ucmd.arg(file_a).arg(file_b).succeeds().no_stderr();

    assert!(!at.file_exists(file_a));
    assert!(!at.file_exists(file_b));
}

#[test]
fn test_rm_interactive() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    let file_a = "test_rm_interactive_file_a";
    let file_b = "test_rm_interactive_file_b";

    at.touch(file_a);
    at.touch(file_b);

    scene
        .ucmd()
        .arg("-i")
        .arg(file_a)
        .arg(file_b)
        .pipe_in("n")
        .succeeds();

    assert!(at.file_exists(file_a));
    assert!(at.file_exists(file_b));

    scene
        .ucmd()
        .arg("-i")
        .arg(file_a)
        .arg(file_b)
        .pipe_in("Yesh")
        .succeeds();

    assert!(!at.file_exists(file_a));
    assert!(at.file_exists(file_b));
}

#[test]
fn test_rm_force() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_rm_force_a";
    let file_b = "test_rm_force_b";

    ucmd.arg("-f")
        .arg(file_a)
        .arg(file_b)
        .succeeds()
        .no_stderr();

    assert!(!at.file_exists(file_a));
    assert!(!at.file_exists(file_b));
}

#[test]
fn test_rm_force_multiple() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_rm_force_a";
    let file_b = "test_rm_force_b";

    ucmd.arg("-f")
        .arg("-f")
        .arg("-f")
        .arg(file_a)
        .arg(file_b)
        .succeeds()
        .no_stderr();

    assert!(!at.file_exists(file_a));
    assert!(!at.file_exists(file_b));
}

#[test]
fn test_rm_empty_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_empty_directory";

    at.mkdir(dir);

    ucmd.arg("-d").arg(dir).succeeds().no_stderr();

    assert!(!at.dir_exists(dir));
}

#[test]
fn test_rm_empty_directory_verbose() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_empty_directory_verbose";

    at.mkdir(dir);

    ucmd.arg("-d")
        .arg("-v")
        .arg(dir)
        .succeeds()
        .stdout_only(format!("removed directory '{}'\n", dir));

    assert!(!at.dir_exists(dir));
}

#[test]
fn test_rm_non_empty_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_non_empty_dir";
    let file_a = &format!("{}/test_rm_non_empty_file_a", dir);

    at.mkdir(dir);
    at.touch(file_a);

    let result = ucmd.arg("-d").arg(dir).fails();
    assert!(result
        .stderr
        .contains(&format!("cannot remove '{}': Directory not empty", dir)));
    assert!(at.file_exists(file_a));
    assert!(at.dir_exists(dir));
}

#[test]
fn test_rm_recursive() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_recursive_directory";
    let file_a = "test_rm_recursive_directory/test_rm_recursive_file_a";
    let file_b = "test_rm_recursive_directory/test_rm_recursive_file_b";

    at.mkdir(dir);
    at.touch(file_a);
    at.touch(file_b);

    ucmd.arg("-r").arg(dir).succeeds().no_stderr();

    assert!(!at.dir_exists(dir));
    assert!(!at.file_exists(file_a));
    assert!(!at.file_exists(file_b));
}

#[test]
fn test_rm_directory_without_flag() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_directory_without_flag_dir";

    at.mkdir(dir);

    let result = ucmd.arg(dir).fails();
    println!("{}", result.stderr);
    assert!(result
        .stderr
        .contains(&format!("cannot remove '{}': Is a directory", dir)));
}

#[test]
fn test_rm_verbose() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_rm_verbose_file_a";
    let file_b = "test_rm_verbose_file_b";

    at.touch(file_a);
    at.touch(file_b);

    ucmd.arg("-v")
        .arg(file_a)
        .arg(file_b)
        .succeeds()
        .stdout_only(format!("removed '{}'\nremoved '{}'\n", file_a, file_b));
}

#[test]
#[cfg(not(windows))]
// on unix symlink_dir is a file
fn test_rm_symlink_dir() {
    let (at, mut ucmd) = at_and_ucmd!();

    let dir = "test_rm_symlink_dir_directory";
    let link = "test_rm_symlink_dir_link";

    at.mkdir(dir);
    at.symlink_dir(dir, link);

    ucmd.arg(link).succeeds();
}

#[test]
#[cfg(windows)]
// on windows removing symlink_dir requires "-r" or "-d"
fn test_rm_symlink_dir() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    let dir = "test_rm_symlink_dir_directory";
    let link = "test_rm_symlink_dir_link";

    at.mkdir(dir);
    at.symlink_dir(dir, link);

    let result = scene.ucmd().arg(link).fails();
    assert!(result
        .stderr
        .contains(&format!("cannot remove '{}': Is a directory", link)));

    assert!(at.dir_exists(link));

    scene.ucmd().arg("-r").arg(link).succeeds();
}

#[test]
fn test_rm_invalid_symlink() {
    let (at, mut ucmd) = at_and_ucmd!();
    let link = "test_rm_invalid_symlink";

    at.symlink_file(link, link);

    ucmd.arg(link).succeeds();
}

#[test]
fn test_rm_force_no_operand() {
    let mut ucmd = new_ucmd!();

    ucmd.arg("-f").succeeds().no_stderr();
}

#[test]
fn test_rm_no_operand() {
    let mut ucmd = new_ucmd!();

    ucmd.fails()
        .stderr_is("rm: error: missing an argument\nrm: error: for help, try 'rm --help'\n");
}

#[test]
fn test_rm_verbose_slash() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_verbose_slash_directory";
    let file_a = &format!("{}/test_rm_verbose_slash_file_a", dir);

    at.mkdir(dir);
    at.touch(file_a);

    let file_a_normalized = &format!(
        "{}{}test_rm_verbose_slash_file_a",
        dir,
        std::path::MAIN_SEPARATOR
    );

    ucmd.arg("-r")
        .arg("-f")
        .arg("-v")
        .arg(&format!("{}///", dir))
        .succeeds()
        .stdout_only(format!(
            "removed '{}'\nremoved directory '{}'\n",
            file_a_normalized, dir
        ));

    assert!(!at.dir_exists(dir));
    assert!(!at.file_exists(file_a));
}
<commit_msg>rm: refactor tests for #1982<commit_after>use crate::common::util::*;

#[test]
fn test_rm_one_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_rm_one_file";

    at.touch(file);

    ucmd.arg(file).succeeds().no_stderr();

    assert!(!at.file_exists(file));
}

#[test]
fn test_rm_failed() {
    let (_at, mut ucmd) = at_and_ucmd!();
    let file = "test_rm_one_file"; // Doesn't exist

    ucmd.arg(file).fails().stderr_contains(&format!(
        "cannot remove '{}': No such file or directory",
        file
    ));
}

#[test]
fn test_rm_multiple_files() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_rm_multiple_file_a";
    let file_b = "test_rm_multiple_file_b";

    at.touch(file_a);
    at.touch(file_b);

    ucmd.arg(file_a).arg(file_b).succeeds().no_stderr();

    assert!(!at.file_exists(file_a));
    assert!(!at.file_exists(file_b));
}

#[test]
fn test_rm_interactive() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    let file_a = "test_rm_interactive_file_a";
    let file_b = "test_rm_interactive_file_b";

    at.touch(file_a);
    at.touch(file_b);

    scene
        .ucmd()
        .arg("-i")
        .arg(file_a)
        .arg(file_b)
        .pipe_in("n")
        .succeeds();

    assert!(at.file_exists(file_a));
    assert!(at.file_exists(file_b));

    scene
        .ucmd()
        .arg("-i")
        .arg(file_a)
        .arg(file_b)
        .pipe_in("Yesh")
        .succeeds();

    assert!(!at.file_exists(file_a));
    assert!(at.file_exists(file_b));
}

#[test]
fn test_rm_force() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_rm_force_a";
    let file_b = "test_rm_force_b";

    ucmd.arg("-f")
        .arg(file_a)
        .arg(file_b)
        .succeeds()
        .no_stderr();

    assert!(!at.file_exists(file_a));
    assert!(!at.file_exists(file_b));
}

#[test]
fn test_rm_force_multiple() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_rm_force_a";
    let file_b = "test_rm_force_b";

    ucmd.arg("-f")
        .arg("-f")
        .arg("-f")
        .arg(file_a)
        .arg(file_b)
        .succeeds()
        .no_stderr();

    assert!(!at.file_exists(file_a));
    assert!(!at.file_exists(file_b));
}

#[test]
fn test_rm_empty_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_empty_directory";

    at.mkdir(dir);

    ucmd.arg("-d").arg(dir).succeeds().no_stderr();

    assert!(!at.dir_exists(dir));
}

#[test]
fn test_rm_empty_directory_verbose() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_empty_directory_verbose";

    at.mkdir(dir);

    ucmd.arg("-d")
        .arg("-v")
        .arg(dir)
        .succeeds()
        .stdout_only(format!("removed directory '{}'\n", dir));

    assert!(!at.dir_exists(dir));
}

#[test]
fn test_rm_non_empty_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_non_empty_dir";
    let file_a = &format!("{}/test_rm_non_empty_file_a", dir);

    at.mkdir(dir);
    at.touch(file_a);

    ucmd.arg("-d")
        .arg(dir)
        .fails()
        .stderr_contains(&format!("cannot remove '{}': Directory not empty", dir));
    assert!(at.file_exists(file_a));
    assert!(at.dir_exists(dir));
}

#[test]
fn test_rm_recursive() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_recursive_directory";
    let file_a = "test_rm_recursive_directory/test_rm_recursive_file_a";
    let file_b = "test_rm_recursive_directory/test_rm_recursive_file_b";

    at.mkdir(dir);
    at.touch(file_a);
    at.touch(file_b);

    ucmd.arg("-r").arg(dir).succeeds().no_stderr();

    assert!(!at.dir_exists(dir));
    assert!(!at.file_exists(file_a));
    assert!(!at.file_exists(file_b));
}

#[test]
fn test_rm_directory_without_flag() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_directory_without_flag_dir";

    at.mkdir(dir);

    ucmd.arg(dir)
        .fails()
        .stderr_contains(&format!("cannot remove '{}': Is a directory", dir));
}

#[test]
fn test_rm_verbose() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_rm_verbose_file_a";
    let file_b = "test_rm_verbose_file_b";

    at.touch(file_a);
    at.touch(file_b);

    ucmd.arg("-v")
        .arg(file_a)
        .arg(file_b)
        .succeeds()
        .stdout_only(format!("removed '{}'\nremoved '{}'\n", file_a, file_b));
}

#[test]
#[cfg(not(windows))]
// on unix symlink_dir is a file
fn test_rm_symlink_dir() {
    let (at, mut ucmd) = at_and_ucmd!();

    let dir = "test_rm_symlink_dir_directory";
    let link = "test_rm_symlink_dir_link";

    at.mkdir(dir);
    at.symlink_dir(dir, link);

    ucmd.arg(link).succeeds();
}

#[test]
#[cfg(windows)]
// on windows removing symlink_dir requires "-r" or "-d"
fn test_rm_symlink_dir() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    let dir = "test_rm_symlink_dir_directory";
    let link = "test_rm_symlink_dir_link";

    at.mkdir(dir);
    at.symlink_dir(dir, link);

    scene
        .ucmd()
        .arg(link)
        .fails()
        .stderr_contains(&format!("cannot remove '{}': Is a directory", link));

    assert!(at.dir_exists(link));

    scene.ucmd().arg("-r").arg(link).succeeds();
}

#[test]
fn test_rm_invalid_symlink() {
    let (at, mut ucmd) = at_and_ucmd!();
    let link = "test_rm_invalid_symlink";

    at.symlink_file(link, link);

    ucmd.arg(link).succeeds();
}

#[test]
fn test_rm_force_no_operand() {
    let mut ucmd = new_ucmd!();

    ucmd.arg("-f").succeeds().no_stderr();
}

#[test]
fn test_rm_no_operand() {
    let mut ucmd = new_ucmd!();

    ucmd.fails()
        .stderr_is("rm: error: missing an argument\nrm: error: for help, try 'rm --help'\n");
}

#[test]
fn test_rm_verbose_slash() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_rm_verbose_slash_directory";
    let file_a = &format!("{}/test_rm_verbose_slash_file_a", dir);

    at.mkdir(dir);
    at.touch(file_a);

    let file_a_normalized = &format!(
        "{}{}test_rm_verbose_slash_file_a",
        dir,
        std::path::MAIN_SEPARATOR
    );

    ucmd.arg("-r")
        .arg("-f")
        .arg("-v")
        .arg(&format!("{}///", dir))
        .succeeds()
        .stdout_only(format!(
            "removed '{}'\nremoved directory '{}'\n",
            file_a_normalized, dir
        ));

    assert!(!at.dir_exists(dir));
    assert!(!at.file_exists(file_a));
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use libc::{c_void, c_int};
use option::Some;
use rt::uv::uvll;
use rt::uv::{Watcher, Loop, NativeHandle, TimerCallback, NullCallback};
use rt::uv::status_to_maybe_uv_error;

pub struct TimerWatcher(*uvll::uv_timer_t);
impl Watcher for TimerWatcher { }

impl TimerWatcher {
    pub fn new(loop_: &mut Loop) -> TimerWatcher {
        unsafe {
            let handle = uvll::malloc_handle(uvll::UV_TIMER);
            assert!(handle.is_not_null());
            assert!(0 == uvll::timer_init(loop_.native_handle(), handle));
            let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
            watcher.install_watcher_data();
            return watcher;
        }
    }

    pub fn start(&mut self, timeout: u64, repeat: u64, cb: TimerCallback) {
        {
            let data = self.get_watcher_data();
            data.timer_cb = Some(cb);
        }

        unsafe {
            uvll::timer_start(self.native_handle(), timer_cb, timeout, repeat);
        }

        extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) {
            let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
            let data = watcher.get_watcher_data();
            let cb = data.timer_cb.get_ref();
            let status = status_to_maybe_uv_error(handle, status);
            (*cb)(watcher, status);
        }
    }

    pub fn stop(&mut self) {
        unsafe {
            uvll::timer_stop(self.native_handle());
        }
    }

    pub fn close(self, cb: NullCallback) {
        let mut watcher = self;
        {
            let data = watcher.get_watcher_data();
            assert!(data.close_cb.is_none());
            data.close_cb = Some(cb);
        }

        unsafe {
            uvll::close(watcher.native_handle(), close_cb);
        }

        extern fn close_cb(handle: *uvll::uv_timer_t) {
            let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
            {
                let data = watcher.get_watcher_data();
                data.close_cb.swap_unwrap()();
            }
            watcher.drop_watcher_data();
            unsafe {
                uvll::free_handle(handle as *c_void);
            }
        }
    }
}

impl NativeHandle<*uvll::uv_timer_t> for TimerWatcher {
    fn from_native_handle(handle: *uvll::uv_timer_t) -> TimerWatcher {
        TimerWatcher(handle)
    }
    fn native_handle(&self) -> *uvll::uv_idle_t {
        match self { &TimerWatcher(ptr) => ptr }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rt::uv::Loop;
    use unstable::run_in_bare_thread;

    #[test]
    fn smoke_test() {
        do run_in_bare_thread {
            let mut count = 0;
            let count_ptr: *mut int = &mut count;
            let mut loop_ = Loop::new();
            let mut timer = TimerWatcher::new(&mut loop_);
            do timer.start(10, 0) |timer, status| {
                assert!(status.is_none());
                unsafe { *count_ptr += 1 };
                timer.close(||());
            }
            loop_.run();
            loop_.close();
            assert!(count == 1);
        }
    }

    #[test]
    fn start_twice() {
        do run_in_bare_thread {
            let mut count = 0;
            let count_ptr: *mut int = &mut count;
            let mut loop_ = Loop::new();
            let mut timer = TimerWatcher::new(&mut loop_);
            do timer.start(10, 0) |timer, status| {
                let mut timer = timer;
                assert!(status.is_none());
                unsafe { *count_ptr += 1 };
                do timer.start(10, 0) |timer, status| {
                    assert!(status.is_none());
                    unsafe { *count_ptr += 1 };
                    timer.close(||());
                }
            }
            loop_.run();
            loop_.close();
            assert!(count == 2);
        }
    }

    #[test]
    fn repeat_stop() {
        do run_in_bare_thread {
            let mut count = 0;
            let count_ptr: *mut int = &mut count;
            let mut loop_ = Loop::new();
            let mut timer = TimerWatcher::new(&mut loop_);
            do timer.start(10, 20) |timer, status| {
                assert!(status.is_none());
                unsafe {
                    *count_ptr += 1;

                    if *count_ptr == 10 {

                        // Stop the timer and do something else
                        let mut timer = timer;
                        timer.stop();
                        // Freeze timer so it can be captured
                        let timer = timer;

                        let mut loop_ = timer.event_loop();
                        let mut timer2 = TimerWatcher::new(&mut loop_);
                        do timer2.start(10, 0) |timer2, _| {

                            unsafe { *count_ptr += 1; }

                            timer2.close(||());

                            // Restart the original timer
                            let mut timer = timer;
                            do timer.start(10, 0) |timer, _| {
                                unsafe { *count_ptr += 1; }
                                timer.close(||());
                            }
                        }
                    }
                };
            }
            loop_.run();
            loop_.close();
            assert!(count == 12);
        }
    }

}
<commit_msg>auto merge of #7195 : brson/rust/timertest, r=bstrie<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use libc::{c_void, c_int};
use option::Some;
use rt::uv::uvll;
use rt::uv::{Watcher, Loop, NativeHandle, TimerCallback, NullCallback};
use rt::uv::status_to_maybe_uv_error;

pub struct TimerWatcher(*uvll::uv_timer_t);
impl Watcher for TimerWatcher { }

impl TimerWatcher {
    pub fn new(loop_: &mut Loop) -> TimerWatcher {
        unsafe {
            let handle = uvll::malloc_handle(uvll::UV_TIMER);
            assert!(handle.is_not_null());
            assert!(0 == uvll::timer_init(loop_.native_handle(), handle));
            let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
            watcher.install_watcher_data();
            return watcher;
        }
    }

    pub fn start(&mut self, timeout: u64, repeat: u64, cb: TimerCallback) {
        {
            let data = self.get_watcher_data();
            data.timer_cb = Some(cb);
        }

        unsafe {
            uvll::timer_start(self.native_handle(), timer_cb, timeout, repeat);
        }

        extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) {
            let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
            let data = watcher.get_watcher_data();
            let cb = data.timer_cb.get_ref();
            let status = status_to_maybe_uv_error(handle, status);
            (*cb)(watcher, status);
        }
    }

    pub fn stop(&mut self) {
        unsafe {
            uvll::timer_stop(self.native_handle());
        }
    }

    pub fn close(self, cb: NullCallback) {
        let mut watcher = self;
        {
            let data = watcher.get_watcher_data();
            assert!(data.close_cb.is_none());
            data.close_cb = Some(cb);
        }

        unsafe {
            uvll::close(watcher.native_handle(), close_cb);
        }

        extern fn close_cb(handle: *uvll::uv_timer_t) {
            let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
            {
                let data = watcher.get_watcher_data();
                data.close_cb.swap_unwrap()();
            }
            watcher.drop_watcher_data();
            unsafe {
                uvll::free_handle(handle as *c_void);
            }
        }
    }
}

impl NativeHandle<*uvll::uv_timer_t> for TimerWatcher {
    fn from_native_handle(handle: *uvll::uv_timer_t) -> TimerWatcher {
        TimerWatcher(handle)
    }
    fn native_handle(&self) -> *uvll::uv_idle_t {
        match self { &TimerWatcher(ptr) => ptr }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rt::uv::Loop;
    use unstable::run_in_bare_thread;

    #[test]
    fn smoke_test() {
        do run_in_bare_thread {
            let mut count = 0;
            let count_ptr: *mut int = &mut count;
            let mut loop_ = Loop::new();
            let mut timer = TimerWatcher::new(&mut loop_);
            do timer.start(10, 0) |timer, status| {
                assert!(status.is_none());
                unsafe { *count_ptr += 1 };
                timer.close(||());
            }
            loop_.run();
            loop_.close();
            assert!(count == 1);
        }
    }

    #[test]
    fn start_twice() {
        do run_in_bare_thread {
            let mut count = 0;
            let count_ptr: *mut int = &mut count;
            let mut loop_ = Loop::new();
            let mut timer = TimerWatcher::new(&mut loop_);
            do timer.start(10, 0) |timer, status| {
                let mut timer = timer;
                assert!(status.is_none());
                unsafe { *count_ptr += 1 };
                do timer.start(10, 0) |timer, status| {
                    assert!(status.is_none());
                    unsafe { *count_ptr += 1 };
                    timer.close(||());
                }
            }
            loop_.run();
            loop_.close();
            assert!(count == 2);
        }
    }

    #[test]
    fn repeat_stop() {
        do run_in_bare_thread {
            let mut count = 0;
            let count_ptr: *mut int = &mut count;
            let mut loop_ = Loop::new();
            let mut timer = TimerWatcher::new(&mut loop_);
            do timer.start(1, 2) |timer, status| {
                assert!(status.is_none());
                unsafe {
                    *count_ptr += 1;

                    if *count_ptr == 10 {

                        // Stop the timer and do something else
                        let mut timer = timer;
                        timer.stop();
                        // Freeze timer so it can be captured
                        let timer = timer;

                        let mut loop_ = timer.event_loop();
                        let mut timer2 = TimerWatcher::new(&mut loop_);
                        do timer2.start(10, 0) |timer2, _| {

                            unsafe { *count_ptr += 1; }

                            timer2.close(||());

                            // Restart the original timer
                            let mut timer = timer;
                            do timer.start(1, 0) |timer, _| {
                                unsafe { *count_ptr += 1; }
                                timer.close(||());
                            }
                        }
                    }
                };
            }
            loop_.run();
            loop_.close();
            assert!(count == 12);
        }
    }

}
<|endoftext|>