<commit_before>//! Various utilities for working with Cairo image surfaces.

use std::mem;
use std::ops::DerefMut;
use std::slice;

pub mod iterators;
pub mod shared_surface;
pub mod srgb;

// These two are for Cairo's platform-endian 0xaarrggbb pixels

#[cfg(target_endian = "little")]
use rgb::alt::BGRA8;
#[cfg(target_endian = "little")]
pub type CairoARGB = BGRA8;

#[cfg(target_endian = "big")]
use rgb::alt::ARGB8;
#[cfg(target_endian = "big")]
pub type CairoARGB = ARGB8;

/// Analogous to `rgb::FromSlice`, to convert from `[T]` to `[CairoARGB]`
pub trait AsCairoARGB<T: Copy> {
    /// Reinterpret slice as `CairoARGB` pixels.
    fn as_cairo_argb(&self) -> &[CairoARGB];

    /// Reinterpret mutable slice as `CairoARGB` pixels.
    fn as_cairo_argb_mut(&mut self) -> &mut [CairoARGB];
}

impl<T: Copy> AsCairoARGB<T> for [T] {
    fn as_cairo_argb(&self) -> &[CairoARGB] {
        debug_assert_eq!(4, mem::size_of::<CairoARGB>() / mem::size_of::<T>());
        unsafe { slice::from_raw_parts(self.as_ptr() as *const _, self.len() / 4) }
    }

    fn as_cairo_argb_mut(&mut self) -> &mut [CairoARGB] {
        debug_assert_eq!(4, mem::size_of::<CairoARGB>() / mem::size_of::<T>());
        unsafe { slice::from_raw_parts_mut(self.as_ptr() as *mut _, self.len() / 4) }
    }
}

/// Modes which specify how the values of out of bounds pixels are computed.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum EdgeMode {
    /// The nearest inbounds pixel value is returned.
    Duplicate,
    /// The image is extended by taking the color values from the opposite of the image.
    ///
    /// Imagine the image being tiled infinitely, with the original image at the origin.
    Wrap,
    /// Zero RGBA values are returned.
    None,
}

/// Extension methods for `cairo::ImageSurfaceData`.
pub trait ImageSurfaceDataExt: DerefMut<Target = [u8]> {
    /// Sets the pixel at the given coordinates. Assumes the `ARgb32` format.
    #[inline]
    fn set_pixel(&mut self, stride: usize, pixel: Pixel, x: u32, y: u32) {
        let value = pixel.to_u32();

        #[allow(clippy::cast_ptr_alignment)]
        unsafe {
            let p: *mut u8 = &mut self[y as usize * stride + x as usize * 4];
            *(p as *mut u32) = value;
        }
    }
}

/// A pixel consisting of R, G, B and A values.
pub type Pixel = rgb::RGBA8;

pub trait PixelOps {
    fn premultiply(self) -> Self;
    fn unpremultiply(self) -> Self;
    fn to_mask(self, opacity: u8) -> Self;
    fn diff(self, other: &Self) -> Self;
    fn to_u32(self) -> u32;
    fn from_u32(x: u32) -> Self;
}

impl PixelOps for Pixel {
    /// Returns an unpremultiplied value of this pixel.
    ///
    /// For a fully transparent pixel, a transparent black pixel will be returned.
    #[inline]
    fn unpremultiply(self) -> Self {
        if self.a == 0 {
            Self {
                r: 0,
                g: 0,
                b: 0,
                a: 0,
            }
        } else {
            let alpha = f32::from(self.a) / 255.0;
            self.map_rgb(|x| ((f32::from(x) / alpha) + 0.5) as u8)
        }
    }

    /// Returns a premultiplied value of this pixel.
    #[inline]
    fn premultiply(self) -> Self {
        let a = self.a as u32;
        self.map_rgb(|x| (((x as u32) * a + 127) / 255) as u8)
    }

    /// Returns a 'mask' pixel with only the alpha channel
    ///
    /// Assuming, the pixel is linear RGB (not sRGB)
    /// y = luminance
    /// Y = 0.2126 R + 0.7152 G + 0.0722 B
    /// 1.0 opacity = 255
    ///
    /// When Y = 1.0, pixel for mask should be 0xFFFFFFFF
    /// (you get 1.0 luminance from 255 from R, G and B)
    ///
    /// r_mult = 0xFFFFFFFF / (255.0 * 255.0) * .2126 = 14042.45  ~= 14042
    /// g_mult = 0xFFFFFFFF / (255.0 * 255.0) * .7152 = 47239.69  ~= 47240
    /// b_mult = 0xFFFFFFFF / (255.0 * 255.0) * .0722 =  4768.88  ~= 4769
    ///
    /// This allows for the following expected behaviour:
    ///    (we only care about the most significant byte)
    /// if pixel = 0x00FFFFFF, pixel' = 0xFF......
    /// if pixel = 0x00020202, pixel' = 0x02......

    /// if pixel = 0x00000000, pixel' = 0x00......
    #[inline]
    fn to_mask(self, opacity: u8) -> Self {
        let r = u32::from(self.r);
        let g = u32::from(self.g);
        let b = u32::from(self.b);
        let o = u32::from(opacity);

        Self {
            r: 0,
            g: 0,
            b: 0,
            a: (((r * 14042 + g * 47240 + b * 4769) * o) >> 24) as u8,
        }
    }

    #[inline]
    fn diff(self, other: &Pixel) -> Pixel {
        self.iter()
            .zip(other.iter())
            .map(|(l, r)| (l as i32 - r as i32).abs() as u8)
            .collect()
    }

    /// Returns the pixel value as a `u32`, in the same format as `cairo::Format::ARgb32`.
    #[inline]
    fn to_u32(self) -> u32 {
        (u32::from(self.a) << 24)
            | (u32::from(self.r) << 16)
            | (u32::from(self.g) << 8)
            | u32::from(self.b)
    }

    /// Converts a `u32` in the same format as `cairo::Format::ARgb32` into a `Pixel`.
    #[inline]
    fn from_u32(x: u32) -> Self {
        Self {
            r: ((x >> 16) & 0xFF) as u8,
            g: ((x >> 8) & 0xFF) as u8,
            b: (x & 0xFF) as u8,
            a: ((x >> 24) & 0xFF) as u8,
        }
    }
}

impl<'a> ImageSurfaceDataExt for cairo::ImageSurfaceData<'a> {}
impl<'a> ImageSurfaceDataExt for &'a mut [u8] {}

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

    #[test]
    fn pixel_diff() {
        let a = Pixel::new(0x10, 0x20, 0xf0, 0x40);
        assert_eq!(a, a.diff(&Pixel::default()));
        let b = Pixel::new(0x50, 0xff, 0x20, 0x10);
        assert_eq!(a.diff(&b), Pixel::new(0x40, 0xdf, 0xd0, 0x30));
    }

    // Floating-point reference implementation
    fn premultiply_float(pixel: Pixel) -> Pixel {
        let alpha = f64::from(pixel.a) / 255.0;
        pixel.map_rgb(|x| ((f64::from(x) * alpha) + 0.5) as u8)
    }

    prop_compose! {
        fn arbitrary_pixel()(a: u8, r: u8, g: u8, b: u8) -> Pixel {
            Pixel { r, g, b, a }
        }
    }

    proptest! {
        #[test]
        fn pixel_premultiply(pixel in arbitrary_pixel()) {
            prop_assert_eq!(pixel.premultiply(), premultiply_float(pixel));
        }

        #[test]
        fn pixel_unpremultiply(pixel in arbitrary_pixel()) {
            let roundtrip = pixel.premultiply().unpremultiply();
            if pixel.a == 0 {
                prop_assert_eq!(roundtrip, Pixel::default());
            } else {
                // roundtrip can't be perfect, the accepted error depends on alpha
                let tolerance = 0xff / pixel.a;
                let diff = roundtrip.diff(&pixel);
                prop_assert!(diff.r <= tolerance, "red component value differs by more than {}: {:?}", tolerance, roundtrip);
                prop_assert!(diff.g <= tolerance, "green component value differs by more than {}: {:?}", tolerance, roundtrip);
                prop_assert!(diff.b <= tolerance, "blue component value differs by more than {}: {:?}", tolerance, roundtrip);

                prop_assert_eq!(pixel.a, roundtrip.a);
            }
       }
    }
}
<commit_msg>Change methods in trait PixelOps to take self by reference<commit_after>//! Various utilities for working with Cairo image surfaces.

use std::mem;
use std::ops::DerefMut;
use std::slice;

pub mod iterators;
pub mod shared_surface;
pub mod srgb;

// These two are for Cairo's platform-endian 0xaarrggbb pixels

#[cfg(target_endian = "little")]
use rgb::alt::BGRA8;
#[cfg(target_endian = "little")]
pub type CairoARGB = BGRA8;

#[cfg(target_endian = "big")]
use rgb::alt::ARGB8;
#[cfg(target_endian = "big")]
pub type CairoARGB = ARGB8;

/// Analogous to `rgb::FromSlice`, to convert from `[T]` to `[CairoARGB]`
pub trait AsCairoARGB<T: Copy> {
    /// Reinterpret slice as `CairoARGB` pixels.
    fn as_cairo_argb(&self) -> &[CairoARGB];

    /// Reinterpret mutable slice as `CairoARGB` pixels.
    fn as_cairo_argb_mut(&mut self) -> &mut [CairoARGB];
}

impl<T: Copy> AsCairoARGB<T> for [T] {
    fn as_cairo_argb(&self) -> &[CairoARGB] {
        debug_assert_eq!(4, mem::size_of::<CairoARGB>() / mem::size_of::<T>());
        unsafe { slice::from_raw_parts(self.as_ptr() as *const _, self.len() / 4) }
    }

    fn as_cairo_argb_mut(&mut self) -> &mut [CairoARGB] {
        debug_assert_eq!(4, mem::size_of::<CairoARGB>() / mem::size_of::<T>());
        unsafe { slice::from_raw_parts_mut(self.as_ptr() as *mut _, self.len() / 4) }
    }
}

/// Modes which specify how the values of out of bounds pixels are computed.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum EdgeMode {
    /// The nearest inbounds pixel value is returned.
    Duplicate,
    /// The image is extended by taking the color values from the opposite of the image.
    ///
    /// Imagine the image being tiled infinitely, with the original image at the origin.
    Wrap,
    /// Zero RGBA values are returned.
    None,
}

/// Extension methods for `cairo::ImageSurfaceData`.
pub trait ImageSurfaceDataExt: DerefMut<Target = [u8]> {
    /// Sets the pixel at the given coordinates. Assumes the `ARgb32` format.
    #[inline]
    fn set_pixel(&mut self, stride: usize, pixel: Pixel, x: u32, y: u32) {
        let value = pixel.to_u32();

        #[allow(clippy::cast_ptr_alignment)]
        unsafe {
            let p: *mut u8 = &mut self[y as usize * stride + x as usize * 4];
            *(p as *mut u32) = value;
        }
    }
}

/// A pixel consisting of R, G, B and A values.
pub type Pixel = rgb::RGBA8;

pub trait PixelOps {
    fn premultiply(self) -> Self;
    fn unpremultiply(self) -> Self;
    fn diff(&self, other: &Self) -> Self;
    fn to_mask(&self, opacity: u8) -> Self;
    fn to_u32(&self) -> u32;
    fn from_u32(x: u32) -> Self;
}

impl PixelOps for Pixel {
    /// Returns an unpremultiplied value of this pixel.
    ///
    /// For a fully transparent pixel, a transparent black pixel will be returned.
    #[inline]
    fn unpremultiply(self) -> Self {
        if self.a == 0 {
            Self {
                r: 0,
                g: 0,
                b: 0,
                a: 0,
            }
        } else {
            let alpha = f32::from(self.a) / 255.0;
            self.map_rgb(|x| ((f32::from(x) / alpha) + 0.5) as u8)
        }
    }

    /// Returns a premultiplied value of this pixel.
    #[inline]
    fn premultiply(self) -> Self {
        let a = self.a as u32;
        self.map_rgb(|x| (((x as u32) * a + 127) / 255) as u8)
    }

    #[inline]
    fn diff(&self, other: &Pixel) -> Pixel {
        self.iter()
            .zip(other.iter())
            .map(|(l, r)| (l as i32 - r as i32).abs() as u8)
            .collect()
    }

    /// Returns a 'mask' pixel with only the alpha channel
    ///
    /// Assuming, the pixel is linear RGB (not sRGB)
    /// y = luminance
    /// Y = 0.2126 R + 0.7152 G + 0.0722 B
    /// 1.0 opacity = 255
    ///
    /// When Y = 1.0, pixel for mask should be 0xFFFFFFFF
    /// (you get 1.0 luminance from 255 from R, G and B)
    ///
    /// r_mult = 0xFFFFFFFF / (255.0 * 255.0) * .2126 = 14042.45  ~= 14042
    /// g_mult = 0xFFFFFFFF / (255.0 * 255.0) * .7152 = 47239.69  ~= 47240
    /// b_mult = 0xFFFFFFFF / (255.0 * 255.0) * .0722 =  4768.88  ~= 4769
    ///
    /// This allows for the following expected behaviour:
    ///    (we only care about the most significant byte)
    /// if pixel = 0x00FFFFFF, pixel' = 0xFF......
    /// if pixel = 0x00020202, pixel' = 0x02......

    /// if pixel = 0x00000000, pixel' = 0x00......
    #[inline]
    fn to_mask(&self, opacity: u8) -> Self {
        let r = u32::from(self.r);
        let g = u32::from(self.g);
        let b = u32::from(self.b);
        let o = u32::from(opacity);

        Self {
            r: 0,
            g: 0,
            b: 0,
            a: (((r * 14042 + g * 47240 + b * 4769) * o) >> 24) as u8,
        }
    }

    /// Returns the pixel value as a `u32`, in the same format as `cairo::Format::ARgb32`.
    #[inline]
    fn to_u32(&self) -> u32 {
        (u32::from(self.a) << 24)
            | (u32::from(self.r) << 16)
            | (u32::from(self.g) << 8)
            | u32::from(self.b)
    }

    /// Converts a `u32` in the same format as `cairo::Format::ARgb32` into a `Pixel`.
    #[inline]
    fn from_u32(x: u32) -> Self {
        Self {
            r: ((x >> 16) & 0xFF) as u8,
            g: ((x >> 8) & 0xFF) as u8,
            b: (x & 0xFF) as u8,
            a: ((x >> 24) & 0xFF) as u8,
        }
    }
}

impl<'a> ImageSurfaceDataExt for cairo::ImageSurfaceData<'a> {}
impl<'a> ImageSurfaceDataExt for &'a mut [u8] {}

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

    #[test]
    fn pixel_diff() {
        let a = Pixel::new(0x10, 0x20, 0xf0, 0x40);
        assert_eq!(a, a.diff(&Pixel::default()));
        let b = Pixel::new(0x50, 0xff, 0x20, 0x10);
        assert_eq!(a.diff(&b), Pixel::new(0x40, 0xdf, 0xd0, 0x30));
    }

    // Floating-point reference implementation
    fn premultiply_float(pixel: Pixel) -> Pixel {
        let alpha = f64::from(pixel.a) / 255.0;
        pixel.map_rgb(|x| ((f64::from(x) * alpha) + 0.5) as u8)
    }

    prop_compose! {
        fn arbitrary_pixel()(a: u8, r: u8, g: u8, b: u8) -> Pixel {
            Pixel { r, g, b, a }
        }
    }

    proptest! {
        #[test]
        fn pixel_premultiply(pixel in arbitrary_pixel()) {
            prop_assert_eq!(pixel.premultiply(), premultiply_float(pixel));
        }

        #[test]
        fn pixel_unpremultiply(pixel in arbitrary_pixel()) {
            let roundtrip = pixel.premultiply().unpremultiply();
            if pixel.a == 0 {
                prop_assert_eq!(roundtrip, Pixel::default());
            } else {
                // roundtrip can't be perfect, the accepted error depends on alpha
                let tolerance = 0xff / pixel.a;
                let diff = roundtrip.diff(&pixel);
                prop_assert!(diff.r <= tolerance, "red component value differs by more than {}: {:?}", tolerance, roundtrip);
                prop_assert!(diff.g <= tolerance, "green component value differs by more than {}: {:?}", tolerance, roundtrip);
                prop_assert!(diff.b <= tolerance, "blue component value differs by more than {}: {:?}", tolerance, roundtrip);

                prop_assert_eq!(pixel.a, roundtrip.a);
            }
       }
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;

use error::{RuntimeError, VoidResult};
use frame::GPUFrame;
use draw::RGB;

use super::super::ffi;
use super::super::{
   Texture, Framebuffer, Shader, Program, viewport, vertex_attrib_pointer,
   enable_vertex_attrib_array, uniform_value_1i, draw_arrays,
};

pub struct QuadFrame {
   pub texture: Texture,
   pub framebuffer: Framebuffer,
   pub program: Program,
   pub vertex_attrib: ffi::GLint,
   pub tex_coord_attrib: ffi::GLint,
   pub tex_sampler_uniform: ffi::GLint,
   pub data: Vec<u8>,
}

impl GPUFrame for QuadFrame {
   #[inline]
   fn new(width: u32, height: u32) -> Result<Self, RuntimeError> {
      let data = Self::create_data(width, height);

      let texture = try!(Texture::new(width, height));
      let framebuffer = try!(Framebuffer::new(&texture));

      try!(texture.bind());
      try!(framebuffer.bind());

      let (program, vertex_attrib, tex_coord_attrib, tex_sampler_uniform) = try!(Self::create_program());

      Ok(QuadFrame {
         texture: texture,
         framebuffer: framebuffer,
         data: data,
         program: program,
         vertex_attrib: vertex_attrib,
         tex_coord_attrib: tex_coord_attrib,
         tex_sampler_uniform: tex_sampler_uniform,
      })
   }

   #[inline]
   fn clear(&mut self) {
      for item in self.data.iter_mut() {
         *item = 0;
      }
   }

   #[inline]
   fn put_pixel(&mut self, x: i32, y: i32, color: &RGB, width: u32, height: u32) {
      if x >= width as i32 || y >= height as i32 || x < 0 || y < 0 {
         return;
      }

      let i = 4 * (x + y * width as i32) as usize;
      self.data[i    ] = color.r;
      self.data[i + 1] = color.g;
      self.data[i + 2] = color.b;
   }

   #[inline]
   fn resize(&mut self, width: u32, height: u32) -> VoidResult {
      self.data.resize((width * height * 4) as usize, 0);
      self.texture.resize(width, height)
   }

   #[inline]
   fn pre_render(&mut self) -> VoidResult {
      Ok(())
   }

   #[inline]
   fn post_render(&mut self, width: u32, height: u32) -> VoidResult {
      let quad_vertices = [
         -1.0, -1.0, 0.0,
         1.0, -1.0, 0.0,
         -1.0, 1.0, 0.0,
         1.0, 1.0, 0.0,
      ];

      let quad_tex_coords = [
         0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
      ];

      try!(self.texture.update(width, height, &self.data));

      try!(viewport(width, height));

      try!(self.program.use_program());

      try!(vertex_attrib_pointer(
         self.vertex_attrib as ffi::GLuint,
         3,
         &quad_vertices
      ));

      try!(vertex_attrib_pointer(
         self.tex_coord_attrib as ffi::GLuint,
         2,
         &quad_tex_coords
      ));

      try!(enable_vertex_attrib_array(self.vertex_attrib as ffi::GLuint));

      try!(enable_vertex_attrib_array(self.tex_coord_attrib as ffi::GLuint));

      try!(uniform_value_1i(self.tex_sampler_uniform, 0));

      draw_arrays(4)
   }
}

impl QuadFrame {
   #[inline]
   pub fn create_data(width: u32, height: u32) -> Vec<u8> {
      repeat(0u8)
         .take((width * height * 4) as usize)
         .collect::<Vec<_>>()
   }

   fn create_program() -> Result<(Program, ffi::GLint, ffi::GLint, ffi::GLint), RuntimeError> {
      let vertex_src = "
         attribute vec4 vertex;
         attribute vec2 texCoord;
         varying vec2 vTexCoord;
         void main()
         {
            gl_Position = vertex;
            vTexCoord = texCoord;
         }
      ";

      let fragment_src = "
         #ifdef GL_ES
            precision mediump float;
         #endif
         varying vec2 vTexCoord;
         uniform sampler2D texSampler;
         void main()
         {
            gl_FragColor = texture2D(texSampler, vTexCoord);
         }
      ";

      let vertex = try!(Shader::new(ffi::GL_VERTEX_SHADER));

      try!(vertex.shader_source(&vertex_src));

      try!(vertex.compile());

      let fragment = try!(Shader::new(ffi::GL_FRAGMENT_SHADER));

      try!(fragment.shader_source(&fragment_src));

      try!(fragment.compile());

      let program = try!(Program::new());

      try!(program.attach_shader(&vertex));
      try!(program.attach_shader(&fragment));

      try!(program.link());

      let vertex_attrib = try!(program.get_attrib_location("vertex"));

      let tex_coord_attrib = try!(program.get_attrib_location("texCoord"));

      let tex_sampler_uniform = try!(program.get_uniform_location("texSampler"));

      Ok((program, vertex_attrib, tex_coord_attrib, tex_sampler_uniform))
   }
}
<commit_msg>Purge the framebuffer calls from the quad frame implementation<commit_after>use std::iter::repeat;

use error::{RuntimeError, VoidResult};
use frame::GPUFrame;
use draw::RGB;

use super::super::ffi;
use super::super::{
   Texture, Shader, Program, viewport, vertex_attrib_pointer,
   enable_vertex_attrib_array, uniform_value_1i, draw_arrays,
};

pub struct QuadFrame {
   pub texture: Texture,
   pub program: Program,
   pub vertex_attrib: ffi::GLint,
   pub tex_coord_attrib: ffi::GLint,
   pub tex_sampler_uniform: ffi::GLint,
   pub data: Vec<u8>,
}

impl GPUFrame for QuadFrame {
   #[inline]
   fn new(width: u32, height: u32) -> Result<Self, RuntimeError> {
      let data = Self::create_data(width, height);

      let texture = try!(Texture::new(width, height));

      try!(texture.bind());

      let (program, vertex_attrib, tex_coord_attrib, tex_sampler_uniform) = try!(Self::create_program());

      Ok(QuadFrame {
         texture: texture,
         data: data,
         program: program,
         vertex_attrib: vertex_attrib,
         tex_coord_attrib: tex_coord_attrib,
         tex_sampler_uniform: tex_sampler_uniform,
      })
   }

   #[inline]
   fn clear(&mut self) {
      for item in self.data.iter_mut() {
         *item = 0;
      }
   }

   #[inline]
   fn put_pixel(&mut self, x: i32, y: i32, color: &RGB, width: u32, height: u32) {
      if x >= width as i32 || y >= height as i32 || x < 0 || y < 0 {
         return;
      }

      let i = 4 * (x + y * width as i32) as usize;
      self.data[i    ] = color.r;
      self.data[i + 1] = color.g;
      self.data[i + 2] = color.b;
   }

   #[inline]
   fn resize(&mut self, width: u32, height: u32) -> VoidResult {
      self.data.resize((width * height * 4) as usize, 0);
      self.texture.resize(width, height)
   }

   #[inline]
   fn pre_render(&mut self) -> VoidResult {
      Ok(())
   }

   #[inline]
   fn post_render(&mut self, width: u32, height: u32) -> VoidResult {
      let quad_vertices = [
         -1.0, -1.0, 0.0,
         1.0, -1.0, 0.0,
         -1.0, 1.0, 0.0,
         1.0, 1.0, 0.0,
      ];

      let quad_tex_coords = [
         0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
      ];

      try!(self.texture.update(width, height, &self.data));

      try!(viewport(width, height));

      try!(self.program.use_program());

      try!(vertex_attrib_pointer(
         self.vertex_attrib as ffi::GLuint,
         3,
         &quad_vertices
      ));

      try!(vertex_attrib_pointer(
         self.tex_coord_attrib as ffi::GLuint,
         2,
         &quad_tex_coords
      ));

      try!(enable_vertex_attrib_array(self.vertex_attrib as ffi::GLuint));

      try!(enable_vertex_attrib_array(self.tex_coord_attrib as ffi::GLuint));

      try!(uniform_value_1i(self.tex_sampler_uniform, 0));

      draw_arrays(4)
   }
}

impl QuadFrame {
   #[inline]
   pub fn create_data(width: u32, height: u32) -> Vec<u8> {
      repeat(0u8)
         .take((width * height * 4) as usize)
         .collect::<Vec<_>>()
   }

   fn create_program() -> Result<(Program, ffi::GLint, ffi::GLint, ffi::GLint), RuntimeError> {
      let vertex_src = "
         attribute vec4 vertex;
         attribute vec2 texCoord;
         varying vec2 vTexCoord;
         void main()
         {
            gl_Position = vertex;
            vTexCoord = texCoord;
         }
      ";

      let fragment_src = "
         #ifdef GL_ES
            precision mediump float;
         #endif
         varying vec2 vTexCoord;
         uniform sampler2D texSampler;
         void main()
         {
            gl_FragColor = texture2D(texSampler, vTexCoord);
         }
      ";

      let vertex = try!(Shader::new(ffi::GL_VERTEX_SHADER));

      try!(vertex.shader_source(&vertex_src));

      try!(vertex.compile());

      let fragment = try!(Shader::new(ffi::GL_FRAGMENT_SHADER));

      try!(fragment.shader_source(&fragment_src));

      try!(fragment.compile());

      let program = try!(Program::new());

      try!(program.attach_shader(&vertex));
      try!(program.attach_shader(&fragment));

      try!(program.link());

      let vertex_attrib = try!(program.get_attrib_location("vertex"));

      let tex_coord_attrib = try!(program.get_attrib_location("texCoord"));

      let tex_sampler_uniform = try!(program.get_uniform_location("texSampler"));

      Ok((program, vertex_attrib, tex_coord_attrib, tex_sampler_uniform))
   }
}
<|endoftext|>


<commit_before>use iron::prelude::*;
use iron::modifiers::Redirect;
use iron::status;
use std::path::{Path, PathBuf};
use std::sync::{Arc, RwLock};

use super::super::builder::Builder;
use super::super::db::GetDb;
use super::super::store::GetStore;
use super::super::web::GetRouter;
use super::util;

pub fn get_docs(request: &mut Request) -> IronResult<Response> {
    let ref name = request.get_router().find("name").unwrap().to_owned();
    let ref version = request.get_router().find("version").unwrap().to_owned();

    let db = request.get_db().clone();
    let store = request.get_store();

    let metadata = util::get_crate(request.get_db(), name);

    if let Err(_) = metadata {
        return Ok(Response::with((status::NotFound)))
    }

    if !metadata.unwrap().versions.contains(&version.to_owned()) {
        return Ok(Response::with((status::NotFound)))
    }

    let pair = format!("{}-{}", name.clone(), version.clone());
    let failed = { db.lock().unwrap().get_failed(&pair) };
    if let Some(failed) = failed {
        return Ok(Response::with((
            status::Ok,
            format!("Unable to build {}:\n\n{}", pair, failed.message)
        )))
    }

    let krate = store.make_crate(name, version);

    let downloaded  = store.contains(&krate);
    let downloading = { db.lock().unwrap().is_build_in_progress(&krate) };

    match (downloaded, downloading) {
        // Not downloaded or downloading, so start a new download and build
        (false, false) => {
            let builder = Builder::new(name, version, krate.clone());

            Builder::spawn(db, Arc::new(RwLock::new(builder)));

            Ok(Response::with((
                status::Ok,
                format!("Building {} version {}...", name, version)
            )))
        },
        // Already downloading/building
        (false, true) => {
            Ok(Response::with((
                status::Ok,
                format!("Already building {} version {}...", name, version)
            )))
        },
        // Downloaded
        (true, false) => {
            Ok(Response::with((
                status::Ok,
                krate.0
            )))
        },
        _ => {
            panic!("Unreachable state: downloaded = {:?}, downloading = {:?}",
                   downloaded,
                   downloading)
        }
    }
}

pub fn get_doc_file(request: &mut Request) -> IronResult<Response> {
    let ref name = request.get_router().find("name").unwrap().to_owned();
    let ref version = request.get_router().find("version").unwrap().to_owned();
    let ref requested_path = sanitize_requested_path(request.get_router().find("path").unwrap());
    let store = request.get_store();

    let krate = store.make_crate(name, version);

    if !store.contains(&krate) {
        return Ok(Response::with((status::NotFound)))
    }

    let mut path_buf = PathBuf::from(krate.0);
    path_buf.extend(Path::new(requested_path));

    if path_buf.is_file() {
        return Ok(Response::with((
            status::Ok,
            path_buf.as_path()
        )))
    }

    // Check if we can serve an "index.html"
    let index_path_buf = path_buf.join(Path::new("index.html"));
    if index_path_buf.is_file() {
        let mut index_url = request.url.clone();
        // Remove a trailing slash if found
        if index_url.path.last().unwrap() == "" {
            index_url.path.pop();
        }
        index_url.path.push("index.html".to_owned());

        return Ok(Response::with((
            status::Found,
            Redirect(index_url)
        )))
    }

    Ok(Response::with((
        status::NotFound,
        format!("Path {} not found in crate documentation", requested_path)
    )))
}

fn sanitize_requested_path(path: &str) -> String {
    let mut path = path;

    // Strip off a trailing slash
    if path.ends_with("/") {
        path = &path[..path.len()-1];
    }

    path.to_owned()
}
<commit_msg>Add request params utility; redirect to docs if docs have been built<commit_after>use iron::prelude::*;
use iron::modifiers::Redirect;
use iron::status;
use std::path::{Path, PathBuf};
use std::sync::{Arc, RwLock};

use super::super::builder::Builder;
use super::super::db::GetDb;
use super::super::store::GetStore;
use super::super::web::GetRouter;
use super::util;

pub fn get_docs(request: &mut Request) -> IronResult<Response> {
    let (name, version) = get_name_and_version(request);
    let db = request.get_db().clone();
    let store = request.get_store();

    let metadata = util::get_crate(request.get_db(), &name);

    if let Err(_) = metadata {
        return Ok(Response::with((status::NotFound)))
    }

    if !metadata.unwrap().versions.contains(&version.to_owned()) {
        return Ok(Response::with((status::NotFound)))
    }

    let pair = format!("{}-{}", name.clone(), version.clone());
    let failed = { db.lock().unwrap().get_failed(&pair) };
    if let Some(failed) = failed {
        return Ok(Response::with((
            status::Ok,
            format!("Unable to build {}:\n\n{}", pair, failed.message)
        )))
    }

    let krate = store.make_crate(&name, &version);

    let downloaded  = store.contains(&krate);
    let downloading = { db.lock().unwrap().is_build_in_progress(&krate) };

    match (downloaded, downloading) {
        // Not downloaded or downloading, so start a new download and build
        (false, false) => {
            let builder = Builder::new(&name, &version, krate.clone());

            Builder::spawn(db, Arc::new(RwLock::new(builder)));

            Ok(Response::with((
                status::Ok,
                format!("Building {} version {}...", name, version)
            )))
        },
        // Already downloading/building
        (false, true) => {
            Ok(Response::with((
                status::Ok,
                format!("Already building {} version {}...", name, version)
            )))
        },
        // Downloaded
        (true, false) => {
            let mut url = request.url.clone();
            url.path.push(name.clone());
            url.path.push("index.html".to_owned());

            return Ok(Response::with((status::Found, Redirect(url))))
        },
        _ => {
            panic!("Unreachable state: downloaded = {:?}, downloading = {:?}",
                   downloaded,
                   downloading)
        }
    }
}

pub fn get_doc_file(request: &mut Request) -> IronResult<Response> {
    let (name, version) = get_name_and_version(request);
    let ref requested_path = sanitize_requested_path(request.get_router().find("path").unwrap());
    let store = request.get_store();

    let krate = store.make_crate(&name, &version);

    if !store.contains(&krate) {
        return Ok(Response::with((status::NotFound)))
    }

    let mut path_buf = PathBuf::from(krate.0);
    path_buf.extend(Path::new(requested_path));

    if path_buf.is_file() {
        return Ok(Response::with((
            status::Ok,
            path_buf.as_path()
        )))
    }

    // Check if we can serve an "index.html"
    let index_path_buf = path_buf.join(Path::new("index.html"));
    if index_path_buf.is_file() {
        let mut index_url = request.url.clone();
        // Remove a trailing slash if found
        if index_url.path.last().unwrap() == "" {
            index_url.path.pop();
        }
        index_url.path.push("index.html".to_owned());

        return Ok(Response::with((
            status::Found,
            Redirect(index_url)
        )))
    }

    Ok(Response::with((
        status::NotFound,
        format!("Path {} not found in crate documentation", requested_path)
    )))
}

fn get_name_and_version(request: &Request) -> (String, String) {
    let ref name = request.get_router().find("name").unwrap().to_owned();
    let ref version = request.get_router().find("version").unwrap().to_owned();

    (name.clone(), version.clone())
}

fn sanitize_requested_path(path: &str) -> String {
    let mut path = path;

    // Strip off a trailing slash
    if path.ends_with("/") {
        path = &path[..path.len()-1];
    }

    path.to_owned()
}
<|endoftext|>


<commit_before>fn main() {
    // statement
    // statement
    // statement
}
<commit_msg>Chapitre 6: révisé<commit_after>fn main() {
    // déclaration
    // déclaration
    // déclaration
}
<|endoftext|>


<commit_before>use libc::{c_int, c_char, c_long, time_t, size_t};
use data_structs::{JTM};
use jalali_bindings::*;
use std::ffi::CString;
use std::{mem, ptr};

pub struct JTMBuilder {
  pub tm_sec: i32,
  pub tm_min: i32,
  pub tm_hour: i32,
  pub tm_mday: i32,
  pub tm_mon: i32,
  pub tm_year: i32,
  pub tm_wday: i32,
  pub tm_yday: i32,
  pub tm_isdst: i32,
  pub tm_gmtoff: i64,
  pub tm_zone: String,
}

impl JTMBuilder {
  pub fn new() -> Self {
    JTMBuilder {
      tm_sec: 0,
      tm_min: 0,
      tm_hour: 0,
      tm_mday: 0,
      tm_mon: 0,
      tm_year: 0,
      tm_wday: 0,
      tm_yday: 0,
      tm_isdst: 0,
      tm_gmtoff: 0,
      tm_zone: "".to_string(),
    }
  }

  pub fn set_sec(&mut self, sec: i32) -> &mut Self {
    self.tm_sec = sec;
    self
  }

  pub fn set_min(&mut self, min: i32) -> &mut Self {
    self.tm_min = min;
    self
  }

  pub fn set_hour(&mut self, hour: i32) -> &mut Self {
    self.tm_hour = hour;
    self
  }

  pub fn set_mday(&mut self, mday: i32) -> &mut Self {
    self.tm_mday = mday;
    self
  }

  pub fn set_mon(&mut self, mon: i32) -> &mut Self {
    self.tm_mon = mon;
    self
  }

  pub fn set_year(&mut self, year: i32) -> &mut Self {
    self.tm_year = year;
    self
  }

  pub fn set_wday(&mut self, wday: i32) -> &mut Self {
    self.tm_wday = wday;
    self
  }

  pub fn set_yday(&mut self, yday: i32) -> &mut Self {
    self.tm_yday = yday;
    self
  }

  pub fn set_isdst(&mut self, isdst: i32) -> &mut Self {
    self.tm_isdst = isdst;
    self
  }

  pub fn set_gmtoff(&mut self, gmtoff: i64) -> &mut Self {
    self.tm_gmtoff = gmtoff;
    self
  }

  pub fn set_zone(&mut self, zone: String) -> &mut Self {
    self.tm_zone = zone;
    self
  }

  pub fn build(&self) -> JTM {
    JTM {
      tm_sec: self.tm_sec,
      tm_min: self.tm_min,
      tm_hour: self.tm_hour,
      tm_mday: self.tm_mday,
      tm_mon: self.tm_mon,
      tm_year: self.tm_year,
      tm_wday: self.tm_wday,
      tm_yday: self.tm_yday,
      tm_isdst: self.tm_isdst,
      tm_gmtoff: self.tm_gmtoff,
      tm_zone: CString::new(self.tm_zone.clone().into_bytes()).
                                                 unwrap().
                                                 into_raw(),
    }
  }
}

impl JTM {
  pub fn from_secs(secs: i64) -> Self {
    let mut result: Self;
    unsafe {
      result = mem::uninitialized();
      jlocaltime_r(&secs as *const time_t, &mut result);
    }
    result
  }

  pub fn from_days(days: i32) -> Self {
    let mut result: Self;
    unsafe {
      result = mem::uninitialized();
      jalali_get_date(days as c_int, &mut result);
    }
    result
  }

  pub fn from_secs_to_utc(secs: i64) -> Self {
    let mut result: Self;
    unsafe {
      result = mem::uninitialized();
      jgmtime_r(&secs as *const time_t, &mut result);
    }
    result
  }

  pub fn from_formatted_string(s: &String, format: &String) -> Result<Self,()> {
    let mut result: Self;
    let tmp;
    unsafe {
      result = mem::uninitialized();
      tmp = jstrptime(s.as_ptr() as *const i8,
                      format.as_ptr() as *const i8,
                      &mut result);
    }
    result.update();
    if tmp.is_null() {
      Err(())
    } else {
      Ok(result)
    }
  }

  pub fn get_timezone(&self) -> String {
    let mut tst = String::with_capacity(5);
    self.make_formated_string(&"%Z".to_string(), &mut tst);
    tst
  }

  pub fn create_date_from_days(&mut self) -> Result<(),()> {
    let tmp = unsafe {
      jalali_create_date_from_days(self)
    };
    match tmp {
      -1 => Err(()),
      _ => Ok(()),
    }
  }

  pub fn create_days_from_date(&mut self) -> Result<(),()> {
    let tmp = unsafe {
      jalali_create_days_from_date(self)
    };
    match tmp {
      -1 => Err(()),
      _ => Ok(()),
    }
  }

  pub fn get_diff(&self) -> i32 {
    unsafe {
      jalali_get_diff(self)
    }
  }

  pub fn update(&mut self) {
    unsafe {
      jalali_update(self);
    }
  }

  pub fn show_time(&self) {
    unsafe {
      jalali_show_time(self);
    }
  }

  pub fn to_string(&self) -> String {
    let mut buff = Vec::<u8>::with_capacity(100);
    let mut result: String;
    unsafe {
      jasctime_r(self, buff.as_mut_ptr() as *mut i8);
      result = CString::from_raw(buff.as_mut_ptr() as *mut i8).into_string().unwrap();
    }
    mem::forget(buff);
    return result;
  }

  pub fn to_secs(&mut self) -> i64 {
    unsafe {
      jmktime(self)
    }
  }

  pub fn make_formated_string(&self, format: &String, buff: &mut String) -> usize {
    let mut b = String::with_capacity(buff.capacity()).into_bytes();
    let retval: usize;
    unsafe {
      let f = format.as_ptr() as *const i8;
      let max = b.capacity() as size_t;
      retval = jstrftime(b.as_mut_ptr() as *mut i8, max, f, self);
      let tmp = CString::from_raw(b.as_mut_ptr() as *mut i8).into_string().unwrap();
      ptr::copy_nonoverlapping(&tmp, buff, 1);
      mem::forget(tmp);
    }
    mem::forget(b);
    return retval;
  }
}
<commit_msg>rename get_diff method to get_days_since_epoch<commit_after>use libc::{c_int, c_char, c_long, time_t, size_t};
use data_structs::{JTM};
use jalali_bindings::*;
use std::ffi::CString;
use std::{mem, ptr};

pub struct JTMBuilder {
  pub tm_sec: i32,
  pub tm_min: i32,
  pub tm_hour: i32,
  pub tm_mday: i32,
  pub tm_mon: i32,
  pub tm_year: i32,
  pub tm_wday: i32,
  pub tm_yday: i32,
  pub tm_isdst: i32,
  pub tm_gmtoff: i64,
  pub tm_zone: String,
}

impl JTMBuilder {
  pub fn new() -> Self {
    JTMBuilder {
      tm_sec: 0,
      tm_min: 0,
      tm_hour: 0,
      tm_mday: 0,
      tm_mon: 0,
      tm_year: 0,
      tm_wday: 0,
      tm_yday: 0,
      tm_isdst: 0,
      tm_gmtoff: 0,
      tm_zone: "".to_string(),
    }
  }

  pub fn set_sec(&mut self, sec: i32) -> &mut Self {
    self.tm_sec = sec;
    self
  }

  pub fn set_min(&mut self, min: i32) -> &mut Self {
    self.tm_min = min;
    self
  }

  pub fn set_hour(&mut self, hour: i32) -> &mut Self {
    self.tm_hour = hour;
    self
  }

  pub fn set_mday(&mut self, mday: i32) -> &mut Self {
    self.tm_mday = mday;
    self
  }

  pub fn set_mon(&mut self, mon: i32) -> &mut Self {
    self.tm_mon = mon;
    self
  }

  pub fn set_year(&mut self, year: i32) -> &mut Self {
    self.tm_year = year;
    self
  }

  pub fn set_wday(&mut self, wday: i32) -> &mut Self {
    self.tm_wday = wday;
    self
  }

  pub fn set_yday(&mut self, yday: i32) -> &mut Self {
    self.tm_yday = yday;
    self
  }

  pub fn set_isdst(&mut self, isdst: i32) -> &mut Self {
    self.tm_isdst = isdst;
    self
  }

  pub fn set_gmtoff(&mut self, gmtoff: i64) -> &mut Self {
    self.tm_gmtoff = gmtoff;
    self
  }

  pub fn set_zone(&mut self, zone: String) -> &mut Self {
    self.tm_zone = zone;
    self
  }

  pub fn build(&self) -> JTM {
    JTM {
      tm_sec: self.tm_sec,
      tm_min: self.tm_min,
      tm_hour: self.tm_hour,
      tm_mday: self.tm_mday,
      tm_mon: self.tm_mon,
      tm_year: self.tm_year,
      tm_wday: self.tm_wday,
      tm_yday: self.tm_yday,
      tm_isdst: self.tm_isdst,
      tm_gmtoff: self.tm_gmtoff,
      tm_zone: CString::new(self.tm_zone.clone().into_bytes()).
                                                 unwrap().
                                                 into_raw(),
    }
  }
}

impl JTM {
  pub fn from_secs(secs: i64) -> Self {
    let mut result: Self;
    unsafe {
      result = mem::uninitialized();
      jlocaltime_r(&secs as *const time_t, &mut result);
    }
    result
  }

  pub fn from_days(days: i32) -> Self {
    let mut result: Self;
    unsafe {
      result = mem::uninitialized();
      jalali_get_date(days as c_int, &mut result);
    }
    result
  }

  pub fn from_secs_to_utc(secs: i64) -> Self {
    let mut result: Self;
    unsafe {
      result = mem::uninitialized();
      jgmtime_r(&secs as *const time_t, &mut result);
    }
    result
  }

  pub fn from_formatted_string(s: &String, format: &String) -> Result<Self,()> {
    let mut result: Self;
    let tmp;
    unsafe {
      result = mem::uninitialized();
      tmp = jstrptime(s.as_ptr() as *const i8,
                      format.as_ptr() as *const i8,
                      &mut result);
    }
    result.update();
    if tmp.is_null() {
      Err(())
    } else {
      Ok(result)
    }
  }

  pub fn get_timezone(&self) -> String {
    let mut tst = String::with_capacity(5);
    self.make_formated_string(&"%Z".to_string(), &mut tst);
    tst
  }

  pub fn create_date_from_days(&mut self) -> Result<(),()> {
    let tmp = unsafe {
      jalali_create_date_from_days(self)
    };
    match tmp {
      -1 => Err(()),
      _ => Ok(()),
    }
  }

  pub fn create_days_from_date(&mut self) -> Result<(),()> {
    let tmp = unsafe {
      jalali_create_days_from_date(self)
    };
    match tmp {
      -1 => Err(()),
      _ => Ok(()),
    }
  }

  pub fn get_days_since_epoch(&self) -> i32 {
    unsafe {
      jalali_get_diff(self)
    }
  }

  pub fn update(&mut self) {
    unsafe {
      jalali_update(self);
    }
  }

  pub fn show_time(&self) {
    unsafe {
      jalali_show_time(self);
    }
  }

  pub fn to_string(&self) -> String {
    let mut buff = Vec::<u8>::with_capacity(100);
    let mut result: String;
    unsafe {
      jasctime_r(self, buff.as_mut_ptr() as *mut i8);
      result = CString::from_raw(buff.as_mut_ptr() as *mut i8).into_string().unwrap();
    }
    mem::forget(buff);
    return result;
  }

  pub fn to_secs(&mut self) -> i64 {
    unsafe {
      jmktime(self)
    }
  }

  pub fn make_formated_string(&self, format: &String, buff: &mut String) -> usize {
    let mut b = String::with_capacity(buff.capacity()).into_bytes();
    let retval: usize;
    unsafe {
      let f = format.as_ptr() as *const i8;
      let max = b.capacity() as size_t;
      retval = jstrftime(b.as_mut_ptr() as *mut i8, max, f, self);
      let tmp = CString::from_raw(b.as_mut_ptr() as *mut i8).into_string().unwrap();
      ptr::copy_nonoverlapping(&tmp, buff, 1);
      mem::forget(tmp);
    }
    mem::forget(b);
    return retval;
  }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

extern mod std;

use std::bitv;
use io::{ReaderUtil, WriterUtil};

// Computes a single solution to a given 9x9 sudoku
//
// Call with "-" to read input sudoku from stdin
//
// The expected line-based format is:
//
// 9,9
// <row>,<column>,<color>
// ...
//
// Row and column are 0-based (i.e. <= 8) and color is 1-based (>=1,<=9).
// A color of 0 indicates an empty field.
//
// If called without arguments, sudoku solves a built-in example sudoku
//

export grid_t, read_grid, solve_grid, write_grid;

// internal type of sudoku grids
type grid = ~[~[u8]];

// exported type of sudoku grids
enum grid_t { grid_ctor(grid), }

// read a sudoku problem from file f
fn read_grid(f: io::Reader) -> grid_t {
    assert f.read_line() == ~"9,9"; /* assert first line is exactly "9,9" */

    let mut g = vec::from_fn(10u, {|_i|
        vec::from_elem(10u, 0 as u8)
    });
    while !f.eof() {
        let comps = str::split_char(str::trim(f.read_line()), ',');
        if vec::len(comps) >= 3u {
            let row     = uint::from_str(comps[0]).get() as u8;
            let col     = uint::from_str(comps[1]).get() as u8;
            g[row][col] = uint::from_str(comps[2]).get() as u8;
        }
    }
    return grid_ctor(g);
}

// solve sudoku grid
fn solve_grid(g: grid_t) {
    fn next_color(mut g: grid, row: u8, col: u8, start_color: u8) -> bool {
        if start_color < 10u8 {
            // colors not yet used
            let avail = bitv::Bitv(10u, false);
            for u8::range(start_color, 10u8) |color| {
                avail.set(color as uint, true);
            }

            // drop colors already in use in neighbourhood
            drop_colors(copy g, copy avail, row, col);

            // find first remaining color that is available
            for uint::range(1u, 10u) |i| {
                if avail.get(i) {
                    g[row][col] = i as u8;
                    return true;
                }
            };
        }
        g[row][col] = 0u8;
        return false;
    }

    // find colors available in neighbourhood of (row, col)
    fn drop_colors(g: grid, avail: bitv::Bitv, row: u8, col: u8) {
        fn drop_color(g: grid, colors: bitv::Bitv, row: u8, col: u8) {
            let color = g[row][col];
            if color != 0u8 { colors.set(color as uint, false); }
        }

        let it = |a,b| drop_color(copy g, copy avail, a, b);

        for u8::range(0u8, 9u8) |idx| {
            it(idx, col); /* check same column fields */
            it(row, idx); /* check same row fields */
        }

        // check same block fields
        let row0 = (row / 3u8) * 3u8;
        let col0 = (col / 3u8) * 3u8;
        for u8::range(row0, row0 + 3u8) |alt_row| {
            for u8::range(col0, col0 + 3u8) |alt_col| { it(alt_row, alt_col); }
        }
    }

    let mut work: ~[(u8, u8)] = ~[]; /* queue of uncolored fields */
    for u8::range(0u8, 9u8) |row| {
        for u8::range(0u8, 9u8) |col| {
            let color = (*g)[row][col];
            if color == 0u8 { work += ~[(row, col)]; }
        }
    }

    let mut ptr = 0u;
    let end = vec::len(work);
    while (ptr < end) {
        let (row, col) = work[ptr];
        // is there another color to try?
        if next_color(copy *g, row, col, (*g)[row][col] + (1 as u8)) {
            //  yes: advance work list
            ptr = ptr + 1u;
        } else {
            // no: redo this field aft recoloring pred; unless there is none
            if ptr == 0u { fail ~"No solution found for this sudoku"; }
            ptr = ptr - 1u;
        }
    }
}

fn write_grid(f: io::Writer, g: grid_t) {
    for u8::range(0u8, 9u8) |row| {
        f.write_str(fmt!("%u", (*g)[row][0] as uint));
        for u8::range(1u8, 9u8) |col| {
            f.write_str(fmt!(" %u", (*g)[row][col] as uint));
        }
        f.write_char('\n');
     }
}

fn main() {
    let args = os::args();
    let grid = if vec::len(args) == 1u {
        // FIXME create sudoku inline since nested vec consts dont work yet
        // (#3733)
        let mut g = vec::from_fn(10u, |_i| {
            vec::from_elem(10u, 0 as u8)
        });
        g[0][1] = 4u8;
        g[0][3] = 6u8;
        g[0][7] = 3u8;
        g[0][8] = 2u8;
        g[1][2] = 8u8;
        g[1][4] = 2u8;
        g[2][0] = 7u8;
        g[2][3] = 8u8;
        g[3][3] = 5u8;
        g[4][1] = 5u8;
        g[4][5] = 3u8;
        g[4][6] = 6u8;
        g[5][0] = 6u8;
        g[5][1] = 8u8;
        g[5][7] = 9u8;
        g[6][1] = 9u8;
        g[6][2] = 5u8;
        g[6][5] = 6u8;
        g[6][7] = 7u8;
        g[7][4] = 4u8;
        g[7][7] = 6u8;
        g[8][0] = 4u8;
        g[8][5] = 7u8;
        g[8][6] = 2u8;
        g[8][8] = 3u8;
        grid_ctor(g)
    } else {
        read_grid(io::stdin())
    };
    solve_grid(copy grid);
    write_grid(io::stdout(), grid);
}

<commit_msg>Fix bench/sudoku, broken by deëxporting<commit_after>// Copyright 2012 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.

extern mod std;

use std::bitv;
use io::{ReaderUtil, WriterUtil};

// Computes a single solution to a given 9x9 sudoku
//
// Call with "-" to read input sudoku from stdin
//
// The expected line-based format is:
//
// 9,9
// <row>,<column>,<color>
// ...
//
// Row and column are 0-based (i.e. <= 8) and color is 1-based (>=1,<=9).
// A color of 0 indicates an empty field.
//
// If called without arguments, sudoku solves a built-in example sudoku
//

// internal type of sudoku grids
type grid = ~[~[u8]];

// exported type of sudoku grids
pub enum grid_t { grid_ctor(grid), }

// read a sudoku problem from file f
pub fn read_grid(f: io::Reader) -> grid_t {
    assert f.read_line() == ~"9,9"; /* assert first line is exactly "9,9" */

    let mut g = vec::from_fn(10u, {|_i|
        vec::from_elem(10u, 0 as u8)
    });
    while !f.eof() {
        let comps = str::split_char(str::trim(f.read_line()), ',');
        if vec::len(comps) >= 3u {
            let row     = uint::from_str(comps[0]).get() as u8;
            let col     = uint::from_str(comps[1]).get() as u8;
            g[row][col] = uint::from_str(comps[2]).get() as u8;
        }
    }
    return grid_ctor(g);
}

// solve sudoku grid
pub fn solve_grid(g: grid_t) {
    fn next_color(mut g: grid, row: u8, col: u8, start_color: u8) -> bool {
        if start_color < 10u8 {
            // colors not yet used
            let avail = bitv::Bitv(10u, false);
            for u8::range(start_color, 10u8) |color| {
                avail.set(color as uint, true);
            }

            // drop colors already in use in neighbourhood
            drop_colors(copy g, copy avail, row, col);

            // find first remaining color that is available
            for uint::range(1u, 10u) |i| {
                if avail.get(i) {
                    g[row][col] = i as u8;
                    return true;
                }
            };
        }
        g[row][col] = 0u8;
        return false;
    }

    // find colors available in neighbourhood of (row, col)
    fn drop_colors(g: grid, avail: bitv::Bitv, row: u8, col: u8) {
        fn drop_color(g: grid, colors: bitv::Bitv, row: u8, col: u8) {
            let color = g[row][col];
            if color != 0u8 { colors.set(color as uint, false); }
        }

        let it = |a,b| drop_color(copy g, copy avail, a, b);

        for u8::range(0u8, 9u8) |idx| {
            it(idx, col); /* check same column fields */
            it(row, idx); /* check same row fields */
        }

        // check same block fields
        let row0 = (row / 3u8) * 3u8;
        let col0 = (col / 3u8) * 3u8;
        for u8::range(row0, row0 + 3u8) |alt_row| {
            for u8::range(col0, col0 + 3u8) |alt_col| { it(alt_row, alt_col); }
        }
    }

    let mut work: ~[(u8, u8)] = ~[]; /* queue of uncolored fields */
    for u8::range(0u8, 9u8) |row| {
        for u8::range(0u8, 9u8) |col| {
            let color = (*g)[row][col];
            if color == 0u8 { work += ~[(row, col)]; }
        }
    }

    let mut ptr = 0u;
    let end = vec::len(work);
    while (ptr < end) {
        let (row, col) = work[ptr];
        // is there another color to try?
        if next_color(copy *g, row, col, (*g)[row][col] + (1 as u8)) {
            //  yes: advance work list
            ptr = ptr + 1u;
        } else {
            // no: redo this field aft recoloring pred; unless there is none
            if ptr == 0u { fail ~"No solution found for this sudoku"; }
            ptr = ptr - 1u;
        }
    }
}

pub fn write_grid(f: io::Writer, g: grid_t) {
    for u8::range(0u8, 9u8) |row| {
        f.write_str(fmt!("%u", (*g)[row][0] as uint));
        for u8::range(1u8, 9u8) |col| {
            f.write_str(fmt!(" %u", (*g)[row][col] as uint));
        }
        f.write_char('\n');
     }
}

fn main() {
    let args = os::args();
    let grid = if vec::len(args) == 1u {
        // FIXME create sudoku inline since nested vec consts dont work yet
        // (#3733)
        let mut g = vec::from_fn(10u, |_i| {
            vec::from_elem(10u, 0 as u8)
        });
        g[0][1] = 4u8;
        g[0][3] = 6u8;
        g[0][7] = 3u8;
        g[0][8] = 2u8;
        g[1][2] = 8u8;
        g[1][4] = 2u8;
        g[2][0] = 7u8;
        g[2][3] = 8u8;
        g[3][3] = 5u8;
        g[4][1] = 5u8;
        g[4][5] = 3u8;
        g[4][6] = 6u8;
        g[5][0] = 6u8;
        g[5][1] = 8u8;
        g[5][7] = 9u8;
        g[6][1] = 9u8;
        g[6][2] = 5u8;
        g[6][5] = 6u8;
        g[6][7] = 7u8;
        g[7][4] = 4u8;
        g[7][7] = 6u8;
        g[8][0] = 4u8;
        g[8][5] = 7u8;
        g[8][6] = 2u8;
        g[8][8] = 3u8;
        grid_ctor(g)
    } else {
        read_grid(io::stdin())
    };
    solve_grid(copy grid);
    write_grid(io::stdout(), grid);
}

<|endoftext|>


<commit_before>extern crate lapin;
#[macro_use] extern crate nom;

use std::net::TcpStream;
use std::iter::repeat;
use std::io::{Read,Write,Error};
use std::collections::HashMap;

use nom::HexDisplay;

use lapin::connection::*;
use lapin::method::*;
use lapin::frame::*;

#[test]
fn connection() {
      let mut stream = TcpStream::connect("127.0.0.1:5672").unwrap();

      let capacity = 4096;
      let mut send_buffer: Vec<u8> = Vec::with_capacity(capacity);
      send_buffer.extend(repeat(0).take(capacity));
      let mut receive_buffer: Vec<u8> = Vec::with_capacity(capacity);
      receive_buffer.extend(repeat(0).take(capacity));

      //let (sl, bytes_written) = gen_protocol_header((&mut send_buffer, 0)).unwrap();
      //assert_eq!(stream.write(&sl[..bytes_written]).unwrap(), bytes_written);

      let mut conn: Connection = Connection::new();
      assert_eq!(conn.connect(&mut stream).unwrap(), ConnectionState::Connecting(ConnectingState::SentProtocolHeader));

      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      //now connected

      let channel_a: u16 = conn.create_channel();
      let channel_b: u16 = conn.create_channel();
      //send channel
      conn.channel_open(channel_a, "".to_string()).expect("channel_open");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      //receive channel
      conn.channel_open(channel_b, "".to_string()).expect("channel_open");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      //create the hello queue
      conn.queue_declare(channel_a, 0, "hello".to_string(), false, false, false, false, false, HashMap::new()).expect("queue_declare");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      conn.queue_declare(channel_b, 0, "hello".to_string(), false, false, false, false, false, HashMap::new()).expect("queue_declare");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());
      panic!();

      println!("will consume");
      conn.basic_consume(channel_b, 0, "hello".to_string(), "".to_string(), false, true, false, false, HashMap::new()).expect("basic_consume");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      println!("will publish");
      conn.basic_publish(channel_a, 0, "".to_string(), "hello".to_string(), false, false).expect("basic_publish");
      let payload = b"Hello world!";
      conn.send_content_frames(channel_a, 60, payload);
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());
      panic!();
}
<commit_msg>use the basic consumer<commit_after>extern crate lapin;
#[macro_use] extern crate nom;

use std::net::TcpStream;
use std::iter::repeat;
use std::io::{Read,Write,Error};
use std::collections::HashMap;
use std::{thread,time};

use nom::HexDisplay;

use lapin::connection::*;
use lapin::method::*;
use lapin::frame::*;
use lapin::callbacks::*;

#[test]
fn connection() {
      let mut stream = TcpStream::connect("127.0.0.1:5672").unwrap();

      let capacity = 4096;
      let mut send_buffer: Vec<u8> = Vec::with_capacity(capacity);
      send_buffer.extend(repeat(0).take(capacity));
      let mut receive_buffer: Vec<u8> = Vec::with_capacity(capacity);
      receive_buffer.extend(repeat(0).take(capacity));

      //let (sl, bytes_written) = gen_protocol_header((&mut send_buffer, 0)).unwrap();
      //assert_eq!(stream.write(&sl[..bytes_written]).unwrap(), bytes_written);

      let mut conn: Connection = Connection::new();
      assert_eq!(conn.connect(&mut stream).unwrap(), ConnectionState::Connecting(ConnectingState::SentProtocolHeader));

      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      //now connected

      let channel_a: u16 = conn.create_channel();
      let channel_b: u16 = conn.create_channel();
      //send channel
      conn.channel_open(channel_a, "".to_string()).expect("channel_open");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      thread::sleep(time::Duration::from_millis(100));
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      //receive channel
      conn.channel_open(channel_b, "".to_string()).expect("channel_open");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      thread::sleep(time::Duration::from_millis(100));
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      //create the hello queue
      conn.queue_declare(channel_a, 0, "hello".to_string(), false, false, false, false, false, HashMap::new()).expect("queue_declare");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      conn.queue_declare(channel_b, 0, "hello".to_string(), false, false, false, false, false, HashMap::new()).expect("queue_declare");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      println!("will consume");
      let consumer = LoggingConsumer{};
      conn.basic_consume(consumer, channel_b, 0, "hello".to_string(), "".to_string(), false, true, false, false, HashMap::new()).expect("basic_consume");
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());

      println!("will publish");
      conn.basic_publish(channel_a, 0, "".to_string(), "hello".to_string(), false, false).expect("basic_publish");
      let payload = b"Hello world!";
      conn.send_content_frames(channel_a, 60, payload);
      println!("[{}] state: {:?}", line!(), conn.write(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.read(&mut stream).unwrap());
      println!("[{}] state: {:?}", line!(), conn.parse().unwrap());
      println!("[{}] state: {:?}", line!(), conn.parse().unwrap());
      panic!();
}
<|endoftext|>


<commit_before>use sdl2::render::RendererContext;
use sdl2::render::Canvas;
use sdl2::video::Window;
use graphicsdevice::GraphicsDevice;
use spritebatchitem::SpriteBatchItem;
use spritebatch::SpriteSortMode;
use spritebatch::SpriteBatch;
use renderstate::RenderState;
use texture::Texture;
use std::i32;
use std::vec;
use vertexpositioncolortexture::VertexPositionColorTexture;

pub struct SpriteBatcher<'a> {
    initial_batch_size: i32,
    max_batch_size: i32,
    initial_vertex_array_size: i32,
    renderer: &'a Canvas<Window>,
    graphics_device: GraphicsDevice,
    batch_item_list: Vec<SpriteBatchItem<'a>>, /// The list of batch items to process.
    batch_item_count: i32, /// Index pointer to the next available SpriteBatchItem in _batchItemList.
    index: Vec<i32>, /// Vertex index array. The values in this array never change.
    vertex_array: Vec<VertexPositionColorTexture>,
}

impl<'a> SpriteBatcher<'a> {
    pub fn new(renderer: &'a Canvas<Window>, graphics_device: GraphicsDevice) -> SpriteBatcher<'a> {
        let mut bil = Vec::new();
        for i in 0..256 {
            bil.push(SpriteBatchItem::new());
        }

        let mut sb = SpriteBatcher {
            initial_batch_size: 256,
            max_batch_size: i32::MAX / 6, // 6 = 4 vertices unique and 2 shared, per quad
            initial_vertex_array_size: 256,
            renderer: renderer,
            graphics_device: graphics_device,
            batch_item_list: bil,
            batch_item_count: 0,
            index: Vec::new(),
            vertex_array: Vec::new(),
        };

        sb.ensure_array_capacity(256);

        sb
    }

    pub fn create_batch_item() -> SpriteBatchItem<'a> {
        SpriteBatchItem::new()
    }

    pub fn ensure_array_capacity(&mut self, num_batch_items: i32) {
        let neededCapacity = 6 * num_batch_items;
        if neededCapacity <= self.index.len() as i32 {
            // Short circuit out of here because we have enough capacity.
            return;
        }

        let mut newIndex: Vec<i32> = Vec::with_capacity(neededCapacity as usize);
        let start = 0;

        for i in 0..self.index.len() as usize {
            newIndex.push(self.index[i]);
        }

        let start = self.index.len() / 6;

        for i in start..num_batch_items as usize {
            /*
            *  TL    TR
            *   0----1 0,1,2,3 = index offsets for vertex indices
            *   |   /| TL,TR,BL,BR are vertex references in SpriteBatchItem.
            *   |  / |
            *   | /  |
            *   |/   |
            *   2----3
            *  BL    BR
            */
            // Triangle 1
            newIndex.insert((i * 6 + 0) as usize, (i * 4) as i32);
            newIndex.insert((i * 6 + 1) as usize, (i * 4 + 1) as i32);
            newIndex.insert((i * 6 + 2) as usize, (i * 4 + 2) as i32);
            // Triangle 2
            newIndex.insert((i * 6 + 3) as usize, (i * 4 + 1) as i32);
            newIndex.insert((i * 6 + 4) as usize, (i * 4 + 3) as i32);
            newIndex.insert((i * 6 + 5) as usize, (i * 4 + 2) as i32);
        }
        self.index = newIndex;

        self.vertex_array.resize(neededCapacity as usize, VertexPositionColorTexture::new());
    }

    pub fn draw_batch(&'a mut self, sort_mode: SpriteSortMode/*, Effect effect*/, render_state: &'a mut RenderState<'a>) {
        // nothing to do
        if self.batch_item_count == 0 {
            return;
        }

        // sort the batch items
        match sort_mode {
            SpriteSortMode::SpriteSortModeTexture => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
            SpriteSortMode::SpriteSortModeFrontToBack => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
            SpriteSortMode::SpriteSortModeBackToFront => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
            _ => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
        }

        // Determine how many iterations through the drawing code we need to make
        let mut batch_index: i32 = 0;
        let mut batch_count: i32 = self.batch_item_count;

        // Iterate through the batches, doing short.MaxValue sets of vertices only.
        while batch_count > 0 {
            // setup the vertexArray array
            let mut startIndex: i32 = 0;
            let mut index: i32 = 0;
            let mut tex: Option<&'a Texture<'a>> = None;

            let mut numBatchesToProcess: i32 = batch_count;
            if numBatchesToProcess > self.max_batch_size {
                numBatchesToProcess = self.max_batch_size;
            }

            {
                self.ensure_array_capacity(numBatchesToProcess);
            }

            // Draw the batches
            for i in 0..numBatchesToProcess {
                // if the texture changed, we need to flush and bind the new texture
                let shouldFlush: bool = &**self.batch_item_list[batch_index as usize].texture.as_ref().unwrap() as *const _ != &**tex.as_ref().unwrap() as *const _;
                if shouldFlush {
                    self.flush_vertex_array(startIndex, index /*, effect*/, tex, render_state);

                    tex = self.batch_item_list[batch_index as usize].texture;
                    startIndex = 0;
                    index = 0;
                }

                let mut item = &mut self.batch_item_list[batch_index as usize];
                // store the SpriteBatchItem data in our vertexArray
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexTL;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexTR;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexBL;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexTR;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexBR;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexBL;

                // Release the texture.
                item.set_texture(None);
            }
            // flush the remaining vertexArray data
            self.flush_vertex_array(startIndex, index /*, effect*/, tex, render_state);
            // Update our batch count to continue the process of culling down
            // large batches
            batch_count -= numBatchesToProcess;
        }
        // return items to the pool.
        self.batch_item_count = 0;
    }

    pub fn flush_vertex_array(&mut self, start: i32, end: i32 /*, Effect effect*/, texture: Option<&'a Texture<'a>>, render_state: &'a mut RenderState<'a>) {
        if start == end {
            return;
        }

        let vertexCount: i32 = end - start;
        render_state.set_texture(texture);

        self.graphics_device.draw(&self.vertex_array, vertexCount, render_state);
    }

}<commit_msg>Fixes the borrow checker errors for the RenderState<commit_after>use sdl2::render::RendererContext;
use sdl2::render::Canvas;
use sdl2::video::Window;
use graphicsdevice::GraphicsDevice;
use spritebatchitem::SpriteBatchItem;
use spritebatch::SpriteSortMode;
use spritebatch::SpriteBatch;
use renderstate::RenderState;
use texture::Texture;
use std::i32;
use std::vec;
use vertexpositioncolortexture::VertexPositionColorTexture;

pub struct SpriteBatcher<'a> {
    initial_batch_size: i32,
    max_batch_size: i32,
    initial_vertex_array_size: i32,
    renderer: &'a Canvas<Window>,
    graphics_device: GraphicsDevice,
    batch_item_list: Vec<SpriteBatchItem<'a>>, /// The list of batch items to process.
    batch_item_count: i32, /// Index pointer to the next available SpriteBatchItem in _batchItemList.
    index: Vec<i32>, /// Vertex index array. The values in this array never change.
    vertex_array: Vec<VertexPositionColorTexture>,
}

impl<'a> SpriteBatcher<'a> {
    pub fn new(renderer: &'a Canvas<Window>, graphics_device: GraphicsDevice) -> SpriteBatcher<'a> {
        let mut bil = Vec::new();
        for i in 0..256 {
            bil.push(SpriteBatchItem::new());
        }

        let mut sb = SpriteBatcher {
            initial_batch_size: 256,
            max_batch_size: i32::MAX / 6, // 6 = 4 vertices unique and 2 shared, per quad
            initial_vertex_array_size: 256,
            renderer: renderer,
            graphics_device: graphics_device,
            batch_item_list: bil,
            batch_item_count: 0,
            index: Vec::new(),
            vertex_array: Vec::new(),
        };

        sb.ensure_array_capacity(256);

        sb
    }

    pub fn create_batch_item() -> SpriteBatchItem<'a> {
        SpriteBatchItem::new()
    }

    pub fn ensure_array_capacity(&mut self, num_batch_items: i32) {
        let neededCapacity = 6 * num_batch_items;
        if neededCapacity <= self.index.len() as i32 {
            // Short circuit out of here because we have enough capacity.
            return;
        }

        let mut newIndex: Vec<i32> = Vec::with_capacity(neededCapacity as usize);
        let start = 0;

        for i in 0..self.index.len() as usize {
            newIndex.push(self.index[i]);
        }

        let start = self.index.len() / 6;

        for i in start..num_batch_items as usize {
            /*
            *  TL    TR
            *   0----1 0,1,2,3 = index offsets for vertex indices
            *   |   /| TL,TR,BL,BR are vertex references in SpriteBatchItem.
            *   |  / |
            *   | /  |
            *   |/   |
            *   2----3
            *  BL    BR
            */
            // Triangle 1
            newIndex.insert((i * 6 + 0) as usize, (i * 4) as i32);
            newIndex.insert((i * 6 + 1) as usize, (i * 4 + 1) as i32);
            newIndex.insert((i * 6 + 2) as usize, (i * 4 + 2) as i32);
            // Triangle 2
            newIndex.insert((i * 6 + 3) as usize, (i * 4 + 1) as i32);
            newIndex.insert((i * 6 + 4) as usize, (i * 4 + 3) as i32);
            newIndex.insert((i * 6 + 5) as usize, (i * 4 + 2) as i32);
        }
        self.index = newIndex;

        self.vertex_array.resize(neededCapacity as usize, VertexPositionColorTexture::new());
    }

    pub fn draw_batch(&'a mut self, sort_mode: SpriteSortMode/*, Effect effect*/, render_state: &'a mut RenderState<'a>) {
        // nothing to do
        if self.batch_item_count == 0 {
            return;
        }

        // sort the batch items
        match sort_mode {
            SpriteSortMode::SpriteSortModeTexture => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
            SpriteSortMode::SpriteSortModeFrontToBack => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
            SpriteSortMode::SpriteSortModeBackToFront => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
            _ => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
        }

        // Determine how many iterations through the drawing code we need to make
        let mut batch_index: i32 = 0;
        let mut batch_count: i32 = self.batch_item_count;

        // Iterate through the batches, doing short.MaxValue sets of vertices only.
        while batch_count > 0 {
            // setup the vertexArray array
            let mut startIndex: i32 = 0;
            let mut index: i32 = 0;
            let mut tex: Option<&'a Texture<'a>> = None;

            let mut numBatchesToProcess: i32 = batch_count;
            if numBatchesToProcess > self.max_batch_size {
                numBatchesToProcess = self.max_batch_size;
            }

            {
                self.ensure_array_capacity(numBatchesToProcess);
            }

            // Draw the batches
            for i in 0..numBatchesToProcess {
                // if the texture changed, we need to flush and bind the new texture
                let shouldFlush: bool = &**self.batch_item_list[batch_index as usize].texture.as_ref().unwrap() as *const _ != &**tex.as_ref().unwrap() as *const _;
                if shouldFlush {
                    self.flush_vertex_array(startIndex, index /*, effect*/, tex, render_state);

                    tex = self.batch_item_list[batch_index as usize].texture;
                    startIndex = 0;
                    index = 0;
                }

                let mut item = &mut self.batch_item_list[batch_index as usize];
                // store the SpriteBatchItem data in our vertexArray
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexTL;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexTR;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexBL;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexTR;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexBR;
                index = index + 1;
                self.vertex_array[index as usize] = item.vertexBL;

                // Release the texture.
                item.set_texture(None);
            }
            // flush the remaining vertexArray data
            self.flush_vertex_array(startIndex, index /*, effect*/, tex, render_state);
            // Update our batch count to continue the process of culling down
            // large batches
            batch_count -= numBatchesToProcess;
        }
        // return items to the pool.
        self.batch_item_count = 0;
    }

    pub fn flush_vertex_array(&mut self, start: i32, end: i32 /*, Effect effect*/, texture: Option<&'a Texture<'a>>, render_state: &mut RenderState<'a>) {
        if start == end {
            return;
        }

        let vertexCount: i32 = end - start;
        render_state.set_texture(texture);

        self.graphics_device.draw(&self.vertex_array, vertexCount, render_state);
    }

}<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::rc::*;

///
/// Identifies a state in a state machine
///
pub type StateId = u32;

///
/// Trait implemented by objects that represent a state machine, whose transitions depend on a particular symbol type
///
/// These state machines can be nondeterministic - which is to say, have more than one transition per state. They always
/// start in state 0.
///
pub trait StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Returns the number of states in this state machine
    ///
    fn count_states(&self) -> StateId;

    ///
    /// Returns the transitions for a particular symbol
    ///
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)>;

    ///
    /// If a state is an accepting state, then this returns the output symbol that should be produced if this is the longest match
    ///
    fn output_symbol_for_state(&self, state: StateId) -> Option<&OutputSymbol>;
}

///
/// Trait implemented by state machines that can be altered
///
pub trait MutableStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Adds a transition from a particular state to another on seeing a symbol
    ///
    fn add_transition(&mut self, state: StateId, for_symbol: InputSymbol, new_state: StateId);

    ///
    /// Sets the output symbol to use for a particular state
    ///
    fn set_output_symbol(&mut self, state: StateId, new_output_symbol: OutputSymbol);
}

///
/// Trait used to indicate that a particular state machine is deterministic (has at most one
/// transition per symbol from the original)
///
pub trait DeterministicStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> { }

///
/// Any reference to a state machine is also a state machine
///
impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<StateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<&OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<&OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> DeterministicStateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
}
<commit_msg>Add some extra documentation<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::rc::*;

//!
//! # State machine
//!
//! The `StateMachine` trait is implemented by anything that represents a state machine (aka a finite state automaton). These
//! consist of one or more states that are transitioned between upon matching a symbol from the input.
//!
//! State machines in this library can optionally attach output symbols to states. A state with an output symbol is an 'accepting'
//! state: it matches a substring of the output.
//!

///
/// Identifies a state in a state machine
///
pub type StateId = u32;

///
/// Trait implemented by objects that represent a state machine, whose transitions depend on a particular symbol type
///
/// These state machines can be nondeterministic - which is to say, have more than one transition per state. They always
/// start in state 0.
///
pub trait StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Returns the number of states in this state machine
    ///
    fn count_states(&self) -> StateId;

    ///
    /// Returns the transitions for a particular symbol
    ///
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)>;

    ///
    /// If a state is an accepting state, then this returns the output symbol that should be produced if this is the longest match
    ///
    fn output_symbol_for_state(&self, state: StateId) -> Option<&OutputSymbol>;
}

///
/// Trait implemented by state machines that can be altered
///
pub trait MutableStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Adds a transition from a particular state to another on seeing a symbol
    ///
    fn add_transition(&mut self, state: StateId, for_symbol: InputSymbol, new_state: StateId);

    ///
    /// Sets the output symbol to use for a particular state
    ///
    fn set_output_symbol(&mut self, state: StateId, new_output_symbol: OutputSymbol);
}

///
/// Trait used to indicate that a particular state machine is deterministic (has at most one
/// transition per symbol from the original)
///
pub trait DeterministicStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> { }

///
/// Any reference to a state machine is also a state machine
///
impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<StateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<&OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<&OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> DeterministicStateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: MPL-2.0
//

use Result;

use easy_process;
use states::{Idle, State, StateChangeImpl, StateMachine};

#[derive(Debug, PartialEq)]
pub struct Reboot {}

create_state_step!(Reboot => Idle);

impl StateChangeImpl for State<Reboot> {
    // FIXME: When adding state-chance hooks, we need to go to Idle if
    // cancelled.
    fn handle(self) -> Result<StateMachine> {
        info!("Triggering reboot");
        let output = easy_process::run("reboot")?;
        if !output.stdout.is_empty() || !output.stderr.is_empty() {
            info!(
                "  reboot output: stdout: {}, stderr: {}",
                output.stdout, output.stderr
            );
        }
        Ok(StateMachine::Idle(self.into()))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::path::Path;

    fn create_reboot(path: &Path) {
        use std::fs::create_dir_all;
        use std::fs::metadata;
        use std::fs::File;
        use std::io::Write;
        use std::os::unix::fs::PermissionsExt;

        // ensure path exists
        create_dir_all(path).unwrap();

        let mut file = File::create(&path.join("reboot")).unwrap();
        file.write_all(b"#!/bin/sh\necho reboot").unwrap();

        let mut permissions = metadata(path).unwrap().permissions();
        permissions.set_mode(0o755);
        file.set_permissions(permissions).unwrap();
    }

    #[test]
    fn runs() {
        use firmware::tests::{create_fake_metadata, FakeDevice};
        use firmware::Metadata;
        use runtime_settings::RuntimeSettings;
        use settings::Settings;
        use std::env;
        use tempfile::tempdir;

        // create the fake reboot command
        let tmpdir = tempdir().unwrap();
        let tmpdir = tmpdir.path();
        create_reboot(&tmpdir);
        env::set_var(
            "PATH",
            format!(
                "{}:{}",
                &tmpdir.to_string_lossy(),
                env::var("PATH").unwrap_or_default()
            ),
        );

        let machine = StateMachine::Reboot(State {
            settings: Settings::default(),
            runtime_settings: RuntimeSettings::default(),
            firmware: Metadata::new(&create_fake_metadata(FakeDevice::NoUpdate)).unwrap(),
            state: Reboot {},
        }).move_to_next_state();

        assert!(machine.is_ok(), "Error: {:?}", machine);
        assert_state!(machine, Idle);
    }
}
<commit_msg>states: reboot: tests: Restrict PATH and simplify mock creation<commit_after>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: MPL-2.0
//

use Result;

use easy_process;
use states::{Idle, State, StateChangeImpl, StateMachine};

#[derive(Debug, PartialEq)]
pub struct Reboot {}

create_state_step!(Reboot => Idle);

impl StateChangeImpl for State<Reboot> {
    // FIXME: When adding state-chance hooks, we need to go to Idle if
    // cancelled.
    fn handle(self) -> Result<StateMachine> {
        info!("Triggering reboot");
        let output = easy_process::run("reboot")?;
        if !output.stdout.is_empty() || !output.stderr.is_empty() {
            info!(
                "  reboot output: stdout: {}, stderr: {}",
                output.stdout, output.stderr
            );
        }
        Ok(StateMachine::Idle(self.into()))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::path::Path;

    fn create_reboot(path: &Path) {
        use std::fs::create_dir_all;
        use std::fs::metadata;
        use std::fs::File;
        use std::io::Write;
        use std::os::unix::fs::PermissionsExt;

        // ensure path exists
        create_dir_all(path).unwrap();

        let mut file = File::create(&path.join("reboot")).unwrap();
        writeln!(file, "#!/bin/sh\necho reboot").unwrap();

        let mut permissions = metadata(path).unwrap().permissions();
        permissions.set_mode(0o755);
        file.set_permissions(permissions).unwrap();
    }

    #[test]
    fn runs() {
        use firmware::tests::{create_fake_metadata, FakeDevice};
        use firmware::Metadata;
        use runtime_settings::RuntimeSettings;
        use settings::Settings;
        use std::env;
        use tempfile::tempdir;

        // create the fake reboot command
        let tmpdir = tempdir().unwrap();
        let tmpdir = tmpdir.path();
        create_reboot(&tmpdir);
        env::set_var("PATH", format!("{}", &tmpdir.to_string_lossy()));

        let machine = StateMachine::Reboot(State {
            settings: Settings::default(),
            runtime_settings: RuntimeSettings::default(),
            firmware: Metadata::new(&create_fake_metadata(FakeDevice::NoUpdate)).unwrap(),
            state: Reboot {},
        }).move_to_next_state();

        assert!(machine.is_ok(), "Error: {:?}", machine);
        assert_state!(machine, Idle);
    }
}
<|endoftext|>