<commit_before>//! An ownership-semantics based handle to OpenGL. This prevents us from
//! accidentally modifying OpenGL state from multiple threads.
//!
//! GLW stands for "OpenGL wrapper".
pub use color::Color4;
use cgmath::array::Array2;
pub use cgmath::matrix::Matrix4;
use cstr_cache;
use libc::types::common::c95;
use gl;
use gl::types::*;
pub use gl::types::GLfloat;
use std::mem;
use std::ptr;
use std::raw;
use std::rc::Rc;
use std::str;
use vertex;

pub struct Shader {
  id: GLuint,
}

impl Shader {
  pub fn new(gl: &mut GLContext, vertex_shader: &str, fragment_shader: &str) -> Shader {
    let vs = gl.compile_shader(vertex_shader, gl::VERTEX_SHADER);
    let fs = gl.compile_shader(fragment_shader, gl::FRAGMENT_SHADER);
    let id = gl.link_shader(vs, fs);
    Shader { id: id }
  }

  /// Sets the variable `proj_matrix` in some shader.
  pub fn set_projection_matrix(&self, gl: &mut GLContext, m: &Matrix4<GLfloat>) {
    let var_name = gl.scache.convert("projection_matrix").as_ptr();
    unsafe {
      let loc = gl::GetUniformLocation(self.id, var_name);
      assert!(loc != -1, "couldn't read projection matrix");
      gl::UniformMatrix4fv(loc, 1, 0, mem::transmute(m.ptr()));
    }
  }
}

impl Drop for Shader {
  fn drop(&mut self) {
    gl::DeleteShader(self.id);
  }
}

/// Gets the id number for a given input of the shader program.
#[allow(non_snake_case_functions)]
fn glGetAttribLocation(shader_program: GLuint, name: &str) -> GLint {
  name.with_c_str(|ptr| unsafe { gl::GetAttribLocation(shader_program, ptr) })
}

#[allow(dead_code)]
unsafe fn println_c_str(str: *const u8) {
  let mut str = str;
  loop {
    let c = *str as char;
    if c == '\0' {
      println!("");
      return;
    }
    print!("{:c}", c);
    str = str.offset(1);
  }
}

/// Ensures a slice has a given alignment, and converts it to a raw pointer.
unsafe fn aligned_slice_to_ptr<T>(vs: &[T], alignment: uint) -> *const c95::c_void {
  let vs_as_slice : raw::Slice<T> = mem::transmute(vs);
  assert_eq!(vs_as_slice.data as uint & (alignment - 1), 0);
  vs_as_slice.data as *const c95::c_void
}

/// A fixed-capacity array of GLfloat-based structures passed to OpenGL.
pub struct GLBuffer<T> {
  vertex_array: u32,
  vertex_buffer: u32,
  /// blocks of size t_span will be treated contiguously.
  t_span: uint,
  /// in units of single Ts.
  length:   uint,
  capacity: uint,
  shader: Rc<Shader>,
  /// How to draw this buffer. Ex: gl::LINES, gl::TRIANGLES, etc.
  mode: GLenum,

  /// in-memory buffer before sending to OpenGL.
  buffer: Vec<T>,
}

pub enum DrawMode {
  Lines,
  Triangles,
}

impl DrawMode {
  fn to_enum(&self) -> GLenum {
    match self {
      &Lines     => gl::LINES,
      &Triangles => gl::TRIANGLES,
    }
  }
}

impl<T: Clone> GLBuffer<T> {
  #[inline]
  /// Creates a new array of objects on the GPU.
  /// capacity is provided in units of size t_span.
  pub fn new(
      _gl: &GLContext,
      shader_program: Rc<Shader>,
      attribs: &[vertex::AttribData],
      t_span: uint,
      capacity: uint,
      mode: DrawMode) -> GLBuffer<T> {
    let capacity = capacity * t_span;
    let mut vertex_array = 0;
    let mut vertex_buffer = 0;

    // TODO(cgaebel): Error checking?

    unsafe {
      gl::GenVertexArrays(1, &mut vertex_array);
      gl::GenBuffers(1, &mut vertex_buffer);
    }

    gl::BindVertexArray(vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer);

    let mut offset = 0;
    for attrib in attribs.iter() {
      let shader_attrib = glGetAttribLocation((*shader_program).id, attrib.name) as GLuint;
      assert!(shader_attrib != -1, "shader attribute \"{}\" not found", attrib.name);

      gl::EnableVertexAttribArray(shader_attrib);
      unsafe {
        gl::VertexAttribPointer(
          shader_attrib,
          attrib.size as i32,
          gl::FLOAT,
          gl::FALSE as GLboolean,
          mem::size_of::<T>() as i32,
          ptr::null().offset(offset),
        );
      }
      offset += (attrib.size * mem::size_of::<GLfloat>()) as int;
    }

    unsafe {
      // Check that the attribs are sized correctly.
      assert_eq!(offset, mem::size_of::<T>() as int);

      gl::BufferData(
        gl::ARRAY_BUFFER,
        (capacity * mem::size_of::<T>()) as GLsizeiptr,
        ptr::null(),
        gl::DYNAMIC_DRAW,
      );
    }

    GLBuffer {
      vertex_array:  vertex_array,
      vertex_buffer: vertex_buffer,
      t_span: t_span,
      length: 0,
      capacity: capacity,
      shader: shader_program,
      mode: mode.to_enum(),
      buffer: Vec::new(),
    }
  }

  /// Analog of vec::Vector::swap_remove`, but for GLBuffer data.
  pub fn swap_remove(&mut self, _gl: &GLContext, i: uint) {
    let i = i * self.t_span;
    assert!(i < self.length);
    self.length -= self.t_span;
    if i == self.length {
      // just remove, no swap.
      return;
    }

    let va = self.vertex_array;
    let vb = self.vertex_buffer;

    gl::BindVertexArray(va);
    gl::BindBuffer(gl::ARRAY_BUFFER, vb);

    let byte_size = mem::size_of::<T>() as i64;
    gl::CopyBufferSubData(
      gl::ARRAY_BUFFER,
      gl::ARRAY_BUFFER,
      self.length as i64 * byte_size,
      i as i64 * byte_size,
      self.t_span as i64 * byte_size
    );
  }

  /// Add more data into this buffer; the data are not pushed to OpenGL until
  /// flush() is called!
  pub fn push(&mut self, vs: &[T]) {
    assert!(vs.len() % self.t_span == 0);
    assert!(
      self.length + self.buffer.len() + vs.len() <= self.capacity,
      "GLBuffer::push into a {}/{} full GLbuffer",
      self.length + self.buffer.len(),
      self.capacity
    );

    self.buffer.push_all(vs);
  }

  /// Send all the in-memory buffered data to OpenGL buffers.
  pub fn flush(&mut self, _gl: &GLContext) {
    if self.buffer.len() > 0 {
      gl::BindVertexArray(self.vertex_array);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

      let size = mem::size_of::<T>() as i64;
      unsafe {
        gl::BufferSubData(
          gl::ARRAY_BUFFER,
          size * self.length as i64,
          size * self.buffer.len() as i64,
          aligned_slice_to_ptr(self.buffer.slice(0, self.buffer.len()), 4)
        );
      }

      self.length += self.buffer.len();
      self.buffer.clear();
    }
  }

  #[inline]
  /// Draws all the queued triangles to the screen.
  pub fn draw(&self, gl: &GLContext) {
    self.draw_slice(gl, 0, self.length);
  }

  /// Draw some subset of the triangle array.
  pub fn draw_slice(&self, gl: &GLContext, start: uint, len: uint) {
    gl.use_shader(self.shader.deref(), |_gl| {
      gl::BindVertexArray(self.vertex_array);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

      gl::DrawArrays(self.mode, start as i32, len as i32);
    });
  }
}

#[unsafe_destructor]
impl<T> Drop for GLBuffer<T> {
  #[inline]
  fn drop(&mut self) {
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer);
      gl::DeleteVertexArrays(1, &self.vertex_array);
    }
  }
}

// TODO(cgaebel): Handle texture creation from an SDL surface.

/// A GPU-allocated texture.
pub struct Texture {
  pub id: GLuint,
}

impl Texture {
  pub fn bind_2d(&self, _gl: &GLContext) {
    gl::BindTexture(gl::TEXTURE_2D, self.id);
  }

  #[allow(dead_code)]
  pub fn bind_3d(&self, _gl: &GLContext) {
    gl::BindTexture(gl::TEXTURE_3D, self.id);
  }
}

impl Drop for Texture {
  fn drop(&mut self) {
    unsafe { gl::DeleteTextures(1, &self.id); }
  }
}

/// A handle to an OpenGL context. Only create one of these per thread.
#[deriving(Send)]
pub struct GLContext {
  scache: cstr_cache::CStringCache,
}

impl GLContext {
  /// Create a new OpenGL context.
  pub fn new() -> GLContext {
    // TODO(cgaebel): Have a thread-local variable checking whether or not
    // there is only one GLContext, and fail if there's more than one.
    GLContext {
      scache: cstr_cache::CStringCache::new(),
    }
  }

  /// Stops the processing of any triangles hidden from view when rendering.
  pub fn enable_culling(&self) {
    gl::FrontFace(gl::CCW);
    gl::CullFace(gl::BACK);
    gl::Enable(gl::CULL_FACE);
  }

  #[allow(missing_doc)]
  pub fn enable_alpha_blending(&self) {
    gl::Enable(gl::BLEND);
    gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
  }

  #[allow(missing_doc)]
  pub fn enable_smooth_lines(&self) {
    gl::Enable(gl::LINE_SMOOTH);
    gl::LineWidth(2.5);
  }

  /// Allows us to use the OpenGL depth buffer, which makes OpenGL do logical
  /// things when two things are rendered at the same x and y coordinates, but
  /// different z coordinates.
  pub fn enable_depth_buffer(&self) {
    gl::Enable(gl::DEPTH_TEST);
    gl::DepthFunc(gl::LESS);
    gl::ClearDepth(100.0);
  }

  /// At the beginning of each frame, OpenGL clears the buffer. This sets the
  /// color the buffer is cleared to.
  pub fn set_background_color(&self, background_color: Color4<GLfloat>) {
    gl::ClearColor(
      background_color.r,
      background_color.g,
      background_color.b,
      background_color.a
    );
  }

  /// Replace the current OpenGL buffer with all pixels of the
  /// "background color", as set with `set_background_color`.
  pub fn clear_buffer(&self) {
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
  }

  /// Compiles a shader for the current graphics card.
  fn compile_shader(&self, src: &str, ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
      // Attempt to compile the shader
      src.with_c_str(|ptr| gl::ShaderSource(shader, 1, &ptr, ptr::null()));
      gl::CompileShader(shader);

      // Get the compile status
      let mut status = gl::FALSE as GLint;
      gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

      // Fail on error
      if status != (gl::TRUE as GLint) {
        let mut len = 0;
        gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
        let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
        gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
        fail!("{}", str::from_utf8(buf.slice(0, buf.len())).expect("ShaderInfoLog not valid utf8"));
      }
    }
    shader
  }

  /// Links a vertex and fragment shader, returning the id of the
  /// resulting program.
  fn link_shader(&self, vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
    let program = gl::CreateProgram();

    gl::AttachShader(program, vertex_shader);
    gl::AttachShader(program, fragment_shader);
    gl::LinkProgram(program);

    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!("{}", str::from_utf8(buf.slice(0, buf.len())).expect("ProgramInfoLog not valid utf8"));
        }
    }

    program
  }

  fn get_current_shader(&self) -> GLuint {
    unsafe {
      let mut ret: GLint = -1;
      gl::GetIntegerv(gl::CURRENT_PROGRAM, &mut ret);
      assert!(ret >= 0, "Need positive shader. Got {}.", ret);
      ret as GLuint
    }
  }

  /// Apply a given shader while rendering the body of the closure.
  pub fn use_shader<T>(&self, shader: &Shader, f: |&GLContext| -> T) -> T {
    // TODO(cgaebel): I heard that OpenGL MIGHT be synchronized on any of the
    // `Get` functions, which means this will be unnecessarily slow. One day
    // we should think about maintaining the shader stack ourselves.
    let old_shader = self.get_current_shader();
    gl::UseProgram(shader.id);
    let r = f(self);
    if old_shader != 0 { gl::UseProgram(old_shader); }
    r
  }

  /// Returns the color of a pixel at (x, y). x and y must be the coordinates
  /// of a pixel in the window. This function will fail if they aren't.
  pub fn read_pixels(&self, x: uint, y: uint, window_height: uint, window_width: uint) -> Color4<u8> {
    assert!(x < window_width, "Expected pixel in range [0, {}), got {}.", window_width, x);
    assert!(y < window_width, "Expected pixel in range [0, {}), got {}.", window_height, y);

    unsafe {
      let pixels: Color4<u8> = Color4::of_rgba(0, 0, 0, 0);
      gl::ReadPixels(x as i32, y as i32, 1, 1, gl::RGB, gl::UNSIGNED_BYTE, mem::transmute(&pixels));
      pixels
    }
  }

  /// Prints opengl version information.
  pub fn print_stats(&self) {
    let opengl_version = gl::GetString(gl::VERSION);
    let glsl_version = gl::GetString(gl::SHADING_LANGUAGE_VERSION);
    print!("OpenGL version: ");
    unsafe { println_c_str(opengl_version); }
    print!("GLSL version: ");
    unsafe { println_c_str(glsl_version); }
    println!("");
  }
}
<commit_msg>Add GLBuffer::update to overwrite data<commit_after>//! An ownership-semantics based handle to OpenGL. This prevents us from
//! accidentally modifying OpenGL state from multiple threads.
//!
//! GLW stands for "OpenGL wrapper".
pub use color::Color4;
use cgmath::array::Array2;
pub use cgmath::matrix::Matrix4;
use cstr_cache;
use libc::types::common::c95;
use gl;
use gl::types::*;
pub use gl::types::GLfloat;
use std::mem;
use std::ptr;
use std::raw;
use std::rc::Rc;
use std::str;
use vertex;

pub struct Shader {
  id: GLuint,
}

impl Shader {
  pub fn new(gl: &mut GLContext, vertex_shader: &str, fragment_shader: &str) -> Shader {
    let vs = gl.compile_shader(vertex_shader, gl::VERTEX_SHADER);
    let fs = gl.compile_shader(fragment_shader, gl::FRAGMENT_SHADER);
    let id = gl.link_shader(vs, fs);
    Shader { id: id }
  }

  /// Sets the variable `proj_matrix` in some shader.
  pub fn set_projection_matrix(&self, gl: &mut GLContext, m: &Matrix4<GLfloat>) {
    let var_name = gl.scache.convert("projection_matrix").as_ptr();
    unsafe {
      let loc = gl::GetUniformLocation(self.id, var_name);
      assert!(loc != -1, "couldn't read projection matrix");
      gl::UniformMatrix4fv(loc, 1, 0, mem::transmute(m.ptr()));
    }
  }
}

impl Drop for Shader {
  fn drop(&mut self) {
    gl::DeleteShader(self.id);
  }
}

/// Gets the id number for a given input of the shader program.
#[allow(non_snake_case_functions)]
fn glGetAttribLocation(shader_program: GLuint, name: &str) -> GLint {
  name.with_c_str(|ptr| unsafe { gl::GetAttribLocation(shader_program, ptr) })
}

#[allow(dead_code)]
unsafe fn println_c_str(str: *const u8) {
  let mut str = str;
  loop {
    let c = *str as char;
    if c == '\0' {
      println!("");
      return;
    }
    print!("{:c}", c);
    str = str.offset(1);
  }
}

/// Ensures a slice has a given alignment, and converts it to a raw pointer.
unsafe fn aligned_slice_to_ptr<T>(vs: &[T], alignment: uint) -> *const c95::c_void {
  let vs_as_slice : raw::Slice<T> = mem::transmute(vs);
  assert_eq!(vs_as_slice.data as uint & (alignment - 1), 0);
  vs_as_slice.data as *const c95::c_void
}

/// A fixed-capacity array of GLfloat-based structures passed to OpenGL.
pub struct GLBuffer<T> {
  vertex_array: u32,
  vertex_buffer: u32,
  /// blocks of size t_span will be treated contiguously.
  t_span: uint,
  /// in units of single Ts.
  length:   uint,
  capacity: uint,
  shader: Rc<Shader>,
  /// How to draw this buffer. Ex: gl::LINES, gl::TRIANGLES, etc.
  mode: GLenum,

  /// in-memory buffer before sending to OpenGL.
  buffer: Vec<T>,
}

pub enum DrawMode {
  Lines,
  Triangles,
}

impl DrawMode {
  fn to_enum(&self) -> GLenum {
    match self {
      &Lines     => gl::LINES,
      &Triangles => gl::TRIANGLES,
    }
  }
}

impl<T: Clone> GLBuffer<T> {
  #[inline]
  /// Creates a new array of objects on the GPU.
  /// capacity is provided in units of size t_span.
  pub fn new(
      _gl: &GLContext,
      shader_program: Rc<Shader>,
      attribs: &[vertex::AttribData],
      t_span: uint,
      capacity: uint,
      mode: DrawMode) -> GLBuffer<T> {
    let capacity = capacity * t_span;
    let mut vertex_array = 0;
    let mut vertex_buffer = 0;

    // TODO(cgaebel): Error checking?

    unsafe {
      gl::GenVertexArrays(1, &mut vertex_array);
      gl::GenBuffers(1, &mut vertex_buffer);
    }

    gl::BindVertexArray(vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer);

    let mut offset = 0;
    for attrib in attribs.iter() {
      let shader_attrib = glGetAttribLocation((*shader_program).id, attrib.name) as GLuint;
      assert!(shader_attrib != -1, "shader attribute \"{}\" not found", attrib.name);

      gl::EnableVertexAttribArray(shader_attrib);
      unsafe {
        gl::VertexAttribPointer(
          shader_attrib,
          attrib.size as i32,
          gl::FLOAT,
          gl::FALSE as GLboolean,
          mem::size_of::<T>() as i32,
          ptr::null().offset(offset),
        );
      }
      offset += (attrib.size * mem::size_of::<GLfloat>()) as int;
    }

    unsafe {
      // Check that the attribs are sized correctly.
      assert_eq!(offset, mem::size_of::<T>() as int);

      gl::BufferData(
        gl::ARRAY_BUFFER,
        (capacity * mem::size_of::<T>()) as GLsizeiptr,
        ptr::null(),
        gl::DYNAMIC_DRAW,
      );
    }

    GLBuffer {
      vertex_array:  vertex_array,
      vertex_buffer: vertex_buffer,
      t_span: t_span,
      length: 0,
      capacity: capacity,
      shader: shader_program,
      mode: mode.to_enum(),
      buffer: Vec::new(),
    }
  }

  /// Analog of vec::Vector::swap_remove`, but for GLBuffer data.
  pub fn swap_remove(&mut self, _gl: &GLContext, i: uint) {
    let i = i * self.t_span;
    assert!(i < self.length);
    self.length -= self.t_span;
    if i == self.length {
      // just remove, no swap.
      return;
    }

    let va = self.vertex_array;
    let vb = self.vertex_buffer;

    gl::BindVertexArray(va);
    gl::BindBuffer(gl::ARRAY_BUFFER, vb);

    let byte_size = mem::size_of::<T>() as i64;
    gl::CopyBufferSubData(
      gl::ARRAY_BUFFER,
      gl::ARRAY_BUFFER,
      self.length as i64 * byte_size,
      i as i64 * byte_size,
      self.t_span as i64 * byte_size
    );
  }

  /// Add more data into this buffer; the data are not pushed to OpenGL until
  /// flush() is called!
  pub fn push(&mut self, vs: &[T]) {
    assert!(vs.len() % self.t_span == 0);
    assert!(
      self.length + self.buffer.len() + vs.len() <= self.capacity,
      "GLBuffer::push into a {}/{} full GLbuffer",
      self.length + self.buffer.len(),
      self.capacity
    );

    self.buffer.push_all(vs);
  }

  /// Send all the in-memory buffered data to OpenGL buffers.
  pub fn flush(&mut self, _gl: &GLContext) {
    assert!(self.buffer.len() % self.t_span == 0);
    if self.buffer.len() > 0 {
      self.update(_gl, self.length / self.t_span, self.buffer.slice(0, self.buffer.len()));

      self.length += self.buffer.len();
      self.buffer.clear();
    }
  }

  pub fn update(&self, _gl: &GLContext, idx: uint, vs: &[T]) {
    assert!(vs.len() % self.t_span == 0);
    assert!(idx * self.t_span + vs.len() <= self.capacity);

    gl::BindVertexArray(self.vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

    let byte_size = mem::size_of::<T>();
    unsafe {
      gl::BufferSubData(
          gl::ARRAY_BUFFER,
          (byte_size * idx * self.t_span) as i64,
          (byte_size * vs.len()) as i64,
          aligned_slice_to_ptr(vs.slice(0, vs.len()), 4)
      );
    }
  }

  #[inline]
  /// Draws all the queued triangles to the screen.
  pub fn draw(&self, gl: &GLContext) {
    self.draw_slice(gl, 0, self.length);
  }

  /// Draw some subset of the triangle array.
  pub fn draw_slice(&self, gl: &GLContext, start: uint, len: uint) {
    gl.use_shader(self.shader.deref(), |_gl| {
      gl::BindVertexArray(self.vertex_array);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

      gl::DrawArrays(self.mode, start as i32, len as i32);
    });
  }
}

#[unsafe_destructor]
impl<T> Drop for GLBuffer<T> {
  #[inline]
  fn drop(&mut self) {
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer);
      gl::DeleteVertexArrays(1, &self.vertex_array);
    }
  }
}

// TODO(cgaebel): Handle texture creation from an SDL surface.

/// A GPU-allocated texture.
pub struct Texture {
  pub id: GLuint,
}

impl Texture {
  pub fn bind_2d(&self, _gl: &GLContext) {
    gl::BindTexture(gl::TEXTURE_2D, self.id);
  }

  #[allow(dead_code)]
  pub fn bind_3d(&self, _gl: &GLContext) {
    gl::BindTexture(gl::TEXTURE_3D, self.id);
  }
}

impl Drop for Texture {
  fn drop(&mut self) {
    unsafe { gl::DeleteTextures(1, &self.id); }
  }
}

/// A handle to an OpenGL context. Only create one of these per thread.
#[deriving(Send)]
pub struct GLContext {
  scache: cstr_cache::CStringCache,
}

impl GLContext {
  /// Create a new OpenGL context.
  pub fn new() -> GLContext {
    // TODO(cgaebel): Have a thread-local variable checking whether or not
    // there is only one GLContext, and fail if there's more than one.
    GLContext {
      scache: cstr_cache::CStringCache::new(),
    }
  }

  /// Stops the processing of any triangles hidden from view when rendering.
  pub fn enable_culling(&self) {
    gl::FrontFace(gl::CCW);
    gl::CullFace(gl::BACK);
    gl::Enable(gl::CULL_FACE);
  }

  #[allow(missing_doc)]
  pub fn enable_alpha_blending(&self) {
    gl::Enable(gl::BLEND);
    gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
  }

  #[allow(missing_doc)]
  pub fn enable_smooth_lines(&self) {
    gl::Enable(gl::LINE_SMOOTH);
    gl::LineWidth(2.5);
  }

  /// Allows us to use the OpenGL depth buffer, which makes OpenGL do logical
  /// things when two things are rendered at the same x and y coordinates, but
  /// different z coordinates.
  pub fn enable_depth_buffer(&self) {
    gl::Enable(gl::DEPTH_TEST);
    gl::DepthFunc(gl::LESS);
    gl::ClearDepth(100.0);
  }

  /// At the beginning of each frame, OpenGL clears the buffer. This sets the
  /// color the buffer is cleared to.
  pub fn set_background_color(&self, background_color: Color4<GLfloat>) {
    gl::ClearColor(
      background_color.r,
      background_color.g,
      background_color.b,
      background_color.a
    );
  }

  /// Replace the current OpenGL buffer with all pixels of the
  /// "background color", as set with `set_background_color`.
  pub fn clear_buffer(&self) {
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
  }

  /// Compiles a shader for the current graphics card.
  fn compile_shader(&self, src: &str, ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
      // Attempt to compile the shader
      src.with_c_str(|ptr| gl::ShaderSource(shader, 1, &ptr, ptr::null()));
      gl::CompileShader(shader);

      // Get the compile status
      let mut status = gl::FALSE as GLint;
      gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

      // Fail on error
      if status != (gl::TRUE as GLint) {
        let mut len = 0;
        gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
        let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
        gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
        fail!("{}", str::from_utf8(buf.slice(0, buf.len())).expect("ShaderInfoLog not valid utf8"));
      }
    }
    shader
  }

  /// Links a vertex and fragment shader, returning the id of the
  /// resulting program.
  fn link_shader(&self, vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
    let program = gl::CreateProgram();

    gl::AttachShader(program, vertex_shader);
    gl::AttachShader(program, fragment_shader);
    gl::LinkProgram(program);

    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!("{}", str::from_utf8(buf.slice(0, buf.len())).expect("ProgramInfoLog not valid utf8"));
        }
    }

    program
  }

  fn get_current_shader(&self) -> GLuint {
    unsafe {
      let mut ret: GLint = -1;
      gl::GetIntegerv(gl::CURRENT_PROGRAM, &mut ret);
      assert!(ret >= 0, "Need positive shader. Got {}.", ret);
      ret as GLuint
    }
  }

  /// Apply a given shader while rendering the body of the closure.
  pub fn use_shader<T>(&self, shader: &Shader, f: |&GLContext| -> T) -> T {
    // TODO(cgaebel): I heard that OpenGL MIGHT be synchronized on any of the
    // `Get` functions, which means this will be unnecessarily slow. One day
    // we should think about maintaining the shader stack ourselves.
    let old_shader = self.get_current_shader();
    gl::UseProgram(shader.id);
    let r = f(self);
    if old_shader != 0 { gl::UseProgram(old_shader); }
    r
  }

  /// Returns the color of a pixel at (x, y). x and y must be the coordinates
  /// of a pixel in the window. This function will fail if they aren't.
  pub fn read_pixels(&self, x: uint, y: uint, window_height: uint, window_width: uint) -> Color4<u8> {
    assert!(x < window_width, "Expected pixel in range [0, {}), got {}.", window_width, x);
    assert!(y < window_width, "Expected pixel in range [0, {}), got {}.", window_height, y);

    unsafe {
      let pixels: Color4<u8> = Color4::of_rgba(0, 0, 0, 0);
      gl::ReadPixels(x as i32, y as i32, 1, 1, gl::RGB, gl::UNSIGNED_BYTE, mem::transmute(&pixels));
      pixels
    }
  }

  /// Prints opengl version information.
  pub fn print_stats(&self) {
    let opengl_version = gl::GetString(gl::VERSION);
    let glsl_version = gl::GetString(gl::SHADING_LANGUAGE_VERSION);
    print!("OpenGL version: ");
    unsafe { println_c_str(opengl_version); }
    print!("GLSL version: ");
    unsafe { println_c_str(glsl_version); }
    println!("");
  }
}
<|endoftext|>


<commit_before>#![no_main]
use arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
use serde::Serialize;

#[derive(Arbitrary, Debug, Serialize)]
enum Value {
    Bool(bool),
    Number(f64),
    String(String),
    Array(Vec<Value>),
    Object(std::collections::HashMap<String, Value>),
}

fuzz_target!(|val: (&str, Value)| {
    let (data, value) = val;
    let mut tpl = tinytemplate::TinyTemplate::new();

    if tpl.add_template("template", data).is_err() {
        return;
    }

    let _ = tinytemplate::TinyTemplate::new().render("template", &value);
});
<commit_msg>Expand fuzzer with multiple inputs<commit_after>#![no_main]
use arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
use serde::Serialize;

#[derive(Arbitrary, Debug, Serialize)]
enum Value {
    Bool(bool),
    Number(f64),
    String(String),
    Array(Vec<Value>),
    Object(std::collections::HashMap<String, Value>),
}

fuzz_target!(|val: (&str, Vec<(&str, &str)>, Value)| {
    let (data, extra, value) = val;
    let mut tpl = tinytemplate::TinyTemplate::new();

    if tpl.add_template("template", data).is_err() {
        return;
    }

    for (name, data) in extra {
        let _ = tpl.add_template(name, data).is_err();
    }

    let _ = tpl.render("template", &value);
});
<|endoftext|>


<commit_before>// Copyright 2017 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 log;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::{self, Body, Pat, PatKind, Expr};
use rustc::middle::region::{RegionMaps, CodeExtent};
use rustc::ty::Ty;
use syntax::ast::NodeId;
use syntax::codemap::Span;
use std::rc::Rc;
use super::FnCtxt;
use util::nodemap::FxHashSet;
use util::nodemap::FxHashMap;

struct InteriorVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
    cache: FxHashMap<NodeId, Option<Span>>,
    types: FxHashSet<Ty<'tcx>>,
    region_maps: Rc<RegionMaps>,
}

impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> {
    fn record(&mut self, ty: Ty<'tcx>, scope: Option<CodeExtent>, expr: Option<&'tcx Expr>) {
        use syntax_pos::DUMMY_SP;

        let live_across_yield = scope.map(|s| {
            self.fcx.tcx.yield_in_extent(s, &mut self.cache).is_some()
        }).unwrap_or(true);

        if live_across_yield {
            if log_enabled!(log::LogLevel::Debug) {
                if let Some(s) = scope {
                    let span = s.span(&self.fcx.tcx.hir).unwrap_or(DUMMY_SP);
                    debug!("type in generator with scope = {:?}, type = {:?}, span = {:?}",
                           scope,
                           self.fcx.resolve_type_vars_if_possible(&ty),
                           span);
                } else {
                    debug!("type in generator WITHOUT scope, type = {:?}",
                           self.fcx.resolve_type_vars_if_possible(&ty));
                }
                if let Some(e) = expr {
                    debug!("type from expression: {:?}, span={:?}", e, e.span);
                }
            }
            self.types.insert(ty);
        } else {
            if let Some(e) = expr {
                debug!("NO type from expression: {:?}, span = {:?}", e, e.span);
            }
        }
    }
}

pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
                                        def_id: DefId,
                                        body_id: hir::BodyId,
                                        witness: Ty<'tcx>) {
    let body = fcx.tcx.hir.body(body_id);
    let mut visitor = InteriorVisitor {
        fcx,
        types: FxHashSet(),
        cache: FxHashMap(),
        region_maps: fcx.tcx.region_maps(def_id),
    };
    intravisit::walk_body(&mut visitor, body);

    // Deduplicate types
    let set: FxHashSet<_> = visitor.types.into_iter()
        .map(|t| fcx.resolve_type_vars_if_possible(&t))
        .collect();
    let types: Vec<_> = set.into_iter().collect();

    let tuple = fcx.tcx.intern_tup(&types, false);

    debug!("Types in generator {:?}, span = {:?}", tuple, body.value.span);

    // Unify the tuple with the witness
    match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(witness, tuple) {
        Ok(ok) => fcx.register_infer_ok_obligations(ok),
        _ => bug!(),
   }
}

impl<'a, 'gcx, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::None
    }

    fn visit_body(&mut self, _body: &'tcx Body) {
        // Closures inside are not considered part of the generator interior
    }

    fn visit_pat(&mut self, pat: &'tcx Pat) {
        if let PatKind::Binding(..) = pat.node {
            let scope = self.region_maps.var_scope(pat.id);
            let ty = self.fcx.tables.borrow().pat_ty(pat);
            self.record(ty, Some(scope), None);
        }

        intravisit::walk_pat(self, pat);
    }

    fn visit_expr(&mut self, expr: &'tcx Expr) {
        let scope = self.region_maps.temporary_scope(expr.id);
        let ty = self.fcx.tables.borrow().expr_ty_adjusted(expr);
        self.record(ty, scope, Some(expr));

        intravisit::walk_expr(self, expr);
    }
}
<commit_msg>Make generator interior types deterministic<commit_after>// Copyright 2017 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 log;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::{self, Body, Pat, PatKind, Expr};
use rustc::middle::region::{RegionMaps, CodeExtent};
use rustc::ty::Ty;
use syntax::ast::NodeId;
use syntax::codemap::Span;
use std::rc::Rc;
use super::FnCtxt;
use util::nodemap::FxHashMap;

struct InteriorVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
    cache: FxHashMap<NodeId, Option<Span>>,

    // FIXME: Use an ordered hash map here
    types: Vec<Ty<'tcx>>,
    region_maps: Rc<RegionMaps>,
}

impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> {
    fn record(&mut self, ty: Ty<'tcx>, scope: Option<CodeExtent>, expr: Option<&'tcx Expr>) {
        use syntax_pos::DUMMY_SP;

        let live_across_yield = scope.map(|s| {
            self.fcx.tcx.yield_in_extent(s, &mut self.cache).is_some()
        }).unwrap_or(true);

        if live_across_yield {
            let ty = self.fcx.resolve_type_vars_if_possible(&ty);

            if log_enabled!(log::LogLevel::Debug) {
                let span = scope.map(|s| s.span(&self.fcx.tcx.hir).unwrap_or(DUMMY_SP));
                debug!("type in expr = {:?}, scope = {:?}, type = {:?}, span = {:?}",
                       expr, scope, ty, span);
            }

            if !self.types.contains(&ty) {
                self.types.push(ty);
            }
        } else {
            debug!("no type in expr = {:?}, span = {:?}", expr, expr.map(|e| e.span));
        }
    }
}

pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
                                        def_id: DefId,
                                        body_id: hir::BodyId,
                                        witness: Ty<'tcx>) {
    let body = fcx.tcx.hir.body(body_id);
    let mut visitor = InteriorVisitor {
        fcx,
        types: Vec::new(),
        cache: FxHashMap(),
        region_maps: fcx.tcx.region_maps(def_id),
    };
    intravisit::walk_body(&mut visitor, body);

    let tuple = fcx.tcx.intern_tup(&visitor.types, false);

    debug!("Types in generator {:?}, span = {:?}", tuple, body.value.span);

    // Unify the tuple with the witness
    match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(witness, tuple) {
        Ok(ok) => fcx.register_infer_ok_obligations(ok),
        _ => bug!(),
   }
}

impl<'a, 'gcx, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::None
    }

    fn visit_body(&mut self, _body: &'tcx Body) {
        // Closures inside are not considered part of the generator interior
    }

    fn visit_pat(&mut self, pat: &'tcx Pat) {
        if let PatKind::Binding(..) = pat.node {
            let scope = self.region_maps.var_scope(pat.id);
            let ty = self.fcx.tables.borrow().pat_ty(pat);
            self.record(ty, Some(scope), None);
        }

        intravisit::walk_pat(self, pat);
    }

    fn visit_expr(&mut self, expr: &'tcx Expr) {
        let scope = self.region_maps.temporary_scope(expr.id);
        let ty = self.fcx.tables.borrow().expr_ty_adjusted(expr);
        self.record(ty, scope, Some(expr));

        intravisit::walk_expr(self, expr);
    }
}
<|endoftext|>


<commit_before>#![deny(missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]

#![cfg_attr(feature = "unstable", allow(unstable_features))]
#![cfg_attr(feature = "unstable", feature(plugin))]
#![cfg_attr(feature = "unstable", plugin(clippy))]

extern crate byteorder;
extern crate flate2;
extern crate regex;
extern crate tabwriter;
extern crate tar;
extern crate time;
#[macro_use] extern crate try_opt;

mod macros;
mod time_utils;
pub mod backend;
pub mod collections;
pub mod signatures;

use std::cell::{Ref, RefCell};
use std::io;

use time::Timespec;

use backend::Backend;
use collections::{BackupChain, BackupSet, Collections};
use signatures::Chain;

#[derive(Debug)]
pub struct Backup<B> {
    backend: B,
    collections: Collections,
    signatures: Vec<RefCell<Option<Chain>>>,
}

pub struct Snapshots<'a> {
    set_iter: CollectionsIter<'a>,
    chain_id: usize,
    sig_id: usize,
    backup: &'a ResourceCache,
}

pub struct Snapshot<'a> {
    set: &'a BackupSet,
    // the number of the parent backup chain, starting from zero
    chain_id: usize,
    sig_id: usize,
    backup: &'a ResourceCache,
}

pub struct SnapshotFiles<'a> {
    chain: Ref<'a, Option<Chain>>,
    sig_id: usize,
}

struct CollectionsIter<'a> {
    chain_iter: collections::ChainIter<'a, BackupChain>,
    incset_iter: Option<collections::BackupSetIter<'a>>,
}

trait ResourceCache {
    fn _collections(&self) -> &Collections;
    fn _signature_chain(&self, chain_id: usize) -> io::Result<Ref<Option<Chain>>>;
}

impl<B: Backend> Backup<B> {
    pub fn new(backend: B) -> io::Result<Self> {
        let files = try!(backend.get_file_names());
        let collections = Collections::from_filenames(files);
        let signatures = {
            // initialize signatures with empty signatures
            // to be loaded lazily
            let mut signatures = Vec::new();
            for _ in collections.signature_chains() {
                signatures.push(RefCell::new(None));
            }
            signatures
        };
        Ok(Backup {
            backend: backend,
            collections: collections,
            signatures: signatures,
        })
    }

    pub fn snapshots(&self) -> Snapshots {
        let set_iter = CollectionsIter {
            chain_iter: self.collections.backup_chains(),
            incset_iter: None,
        };
        Snapshots {
            set_iter: set_iter,
            chain_id: 0,
            sig_id: 0,
            backup: self,
        }
    }
}

impl<'a> Iterator for Snapshots<'a> {
    type Item = Snapshot<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        // first test if we have a valid iterator to an incset
        if let Some(ref mut incset_iter) = self.set_iter.incset_iter {
            // we have a set iter, so return the next element if present
            if let Some(inc_set) = incset_iter.next() {
                self.sig_id += 1;
                return Some(Snapshot {
                    set: inc_set,
                    chain_id: self.chain_id,
                    sig_id: self.sig_id,
                    backup: self.backup,
                });
            }
        }
        // the current incset is exausted or not present,
        // we need to advance the chain and return the next full set if present,
        // otherwise the job is finished
        if let Some(chain) = self.set_iter.chain_iter.next() {
            self.chain_id += 1;
            self.sig_id = 0;
            self.set_iter.incset_iter = Some(chain.inc_sets());
            Some(Snapshot {
                set: chain.full_set(),
                chain_id: self.chain_id - 1,
                sig_id: self.sig_id,
                backup: self.backup,
            })
        } else {
            None
        }
    }
}

impl<'a> AsRef<Collections> for Snapshots<'a> {
    fn as_ref(&self) -> &Collections {
        self.backup._collections()
    }
}

impl<'a> Snapshot<'a> {
    pub fn time(&self) -> Timespec {
        self.set.end_time()
    }

    pub fn is_full(&self) -> bool {
        self.set.is_full()
    }

    pub fn is_incremental(&self) -> bool {
        self.set.is_incremental()
    }

    pub fn num_volumes(&self) -> usize {
        self.set.num_volumes()
    }

    pub fn files(&self) -> io::Result<SnapshotFiles> {
        let sig = try!(self.backup._signature_chain(self.chain_id));
        if self.sig_id < sig.as_ref().unwrap().snapshots().len() {
            Ok(SnapshotFiles {
                chain: sig,
                sig_id: self.sig_id,
            })
        } else {
            Err(io::Error::new(io::ErrorKind::NotFound, "The signature chain is incomplete"))
        }
    }
}

impl<'a> AsRef<BackupSet> for Snapshot<'a> {
    fn as_ref(&self) -> &BackupSet {
        self.set
    }
}

impl<'a> SnapshotFiles<'a> {
    pub fn as_signature_info(&self) -> signatures::SnapshotFiles {
        self.chain.as_ref().unwrap().snapshots().nth(self.sig_id).unwrap().files()
    }
}

impl<B: Backend> ResourceCache for Backup<B> {
    fn _collections(&self) -> &Collections {
        &self.collections
    }

    fn _signature_chain(&self, chain_id: usize) -> io::Result<Ref<Option<Chain>>> {
        {
            // check if there is a cached value
            let mut sig = self.signatures[chain_id].borrow_mut();
            if sig.is_none() {
                // compute signatures now
                if let Some(sigchain) = self.collections.signature_chains().nth(chain_id) {
                    let new_sig = try!(Chain::from_sigchain(sigchain, &self.backend));
                    *sig = Some(new_sig);
                } else {
                    return Err(io::Error::new(io::ErrorKind::NotFound,
                                              "The given backup snapshot does not have a \
                                              corresponding signature"));
                }
            }
        }

        // need to close previous scope to borrow again
        // return the cached value
        Ok(self.signatures[chain_id].borrow())
    }
}
<commit_msg>Fixed bug in Snapshots iteration<commit_after>#![deny(missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]

#![cfg_attr(feature = "unstable", allow(unstable_features))]
#![cfg_attr(feature = "unstable", feature(plugin))]
#![cfg_attr(feature = "unstable", plugin(clippy))]

extern crate byteorder;
extern crate flate2;
extern crate regex;
extern crate tabwriter;
extern crate tar;
extern crate time;
#[macro_use] extern crate try_opt;

mod macros;
mod time_utils;
pub mod backend;
pub mod collections;
pub mod signatures;

use std::cell::{Ref, RefCell};
use std::io;

use time::Timespec;

use backend::Backend;
use collections::{BackupChain, BackupSet, Collections};
use signatures::Chain;

#[derive(Debug)]
pub struct Backup<B> {
    backend: B,
    collections: Collections,
    signatures: Vec<RefCell<Option<Chain>>>,
}

pub struct Snapshots<'a> {
    set_iter: CollectionsIter<'a>,
    chain_id: usize,
    sig_id: usize,
    backup: &'a ResourceCache,
}

pub struct Snapshot<'a> {
    set: &'a BackupSet,
    // the number of the parent backup chain, starting from zero
    chain_id: usize,
    sig_id: usize,
    backup: &'a ResourceCache,
}

pub struct SnapshotFiles<'a> {
    chain: Ref<'a, Option<Chain>>,
    sig_id: usize,
}

struct CollectionsIter<'a> {
    chain_iter: collections::ChainIter<'a, BackupChain>,
    incset_iter: Option<collections::BackupSetIter<'a>>,
}

trait ResourceCache {
    fn _collections(&self) -> &Collections;
    fn _signature_chain(&self, chain_id: usize) -> io::Result<Ref<Option<Chain>>>;
}

impl<B: Backend> Backup<B> {
    pub fn new(backend: B) -> io::Result<Self> {
        let files = try!(backend.get_file_names());
        let collections = Collections::from_filenames(files);
        let signatures = {
            // initialize signatures with empty signatures
            // to be loaded lazily
            let mut signatures = Vec::new();
            for _ in collections.signature_chains() {
                signatures.push(RefCell::new(None));
            }
            signatures
        };
        Ok(Backup {
            backend: backend,
            collections: collections,
            signatures: signatures,
        })
    }

    pub fn snapshots(&self) -> Snapshots {
        let set_iter = CollectionsIter {
            chain_iter: self.collections.backup_chains(),
            incset_iter: None,
        };
        Snapshots {
            set_iter: set_iter,
            chain_id: 0,
            sig_id: 0,
            backup: self,
        }
    }
}

impl<'a> Iterator for Snapshots<'a> {
    type Item = Snapshot<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        // first test if we have a valid iterator to an incset
        if let Some(ref mut incset_iter) = self.set_iter.incset_iter {
            // we have a set iter, so return the next element if present
            if let Some(inc_set) = incset_iter.next() {
                self.sig_id += 1;
                return Some(Snapshot {
                    set: inc_set,
                    chain_id: self.chain_id - 1,
                    sig_id: self.sig_id,
                    backup: self.backup,
                });
            }
        }
        // the current incset is exausted or not present,
        // we need to advance the chain and return the next full set if present,
        // otherwise the job is finished
        if let Some(chain) = self.set_iter.chain_iter.next() {
            self.chain_id += 1;
            self.sig_id = 0;
            self.set_iter.incset_iter = Some(chain.inc_sets());
            Some(Snapshot {
                set: chain.full_set(),
                chain_id: self.chain_id - 1,
                sig_id: self.sig_id,
                backup: self.backup,
            })
        } else {
            None
        }
    }
}

impl<'a> AsRef<Collections> for Snapshots<'a> {
    fn as_ref(&self) -> &Collections {
        self.backup._collections()
    }
}

impl<'a> Snapshot<'a> {
    pub fn time(&self) -> Timespec {
        self.set.end_time()
    }

    pub fn is_full(&self) -> bool {
        self.set.is_full()
    }

    pub fn is_incremental(&self) -> bool {
        self.set.is_incremental()
    }

    pub fn num_volumes(&self) -> usize {
        self.set.num_volumes()
    }

    pub fn files(&self) -> io::Result<SnapshotFiles> {
        let sig = try!(self.backup._signature_chain(self.chain_id));
        if self.sig_id < sig.as_ref().unwrap().snapshots().len() {
            Ok(SnapshotFiles {
                chain: sig,
                sig_id: self.sig_id,
            })
        } else {
            Err(io::Error::new(io::ErrorKind::NotFound, "The signature chain is incomplete"))
        }
    }
}

impl<'a> AsRef<BackupSet> for Snapshot<'a> {
    fn as_ref(&self) -> &BackupSet {
        self.set
    }
}

impl<'a> SnapshotFiles<'a> {
    pub fn as_signature_info(&self) -> signatures::SnapshotFiles {
        self.chain.as_ref().unwrap().snapshots().nth(self.sig_id).unwrap().files()
    }
}

impl<B: Backend> ResourceCache for Backup<B> {
    fn _collections(&self) -> &Collections {
        &self.collections
    }

    fn _signature_chain(&self, chain_id: usize) -> io::Result<Ref<Option<Chain>>> {
        {
            // check if there is a cached value
            let mut sig = self.signatures[chain_id].borrow_mut();
            if sig.is_none() {
                // compute signatures now
                if let Some(sigchain) = self.collections.signature_chains().nth(chain_id) {
                    let new_sig = try!(Chain::from_sigchain(sigchain, &self.backend));
                    *sig = Some(new_sig);
                } else {
                    return Err(io::Error::new(io::ErrorKind::NotFound,
                                              "The given backup snapshot does not have a \
                                              corresponding signature"));
                }
            }
        }

        // need to close previous scope to borrow again
        // return the cached value
        Ok(self.signatures[chain_id].borrow())
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate pbr;
extern crate ansi_term;

use std::sync::{Arc, Mutex};

#[macro_use]
pub mod logs;

pub mod authorization;
pub mod cargo_helper;
pub mod client;
pub mod contentlength;
pub mod download;
pub mod filesize;
pub mod http_version;
pub mod response;
pub mod util;
pub mod write;

/// Represents a number of bytes, as `u64`.
pub type Bytes = u64;
/// Represents a 'chunk', which is just a piece of bytes.
type Chunk = Vec<u8>;
/// Represents a list of chunks
pub type Chunks = Vec<Chunk>;
/// Represents a shared mutable reference of chunks
pub type SChunks = Arc<Mutex<Chunks>>;
/// Represents an URL
pub type URL<'a> = &'a str;
<commit_msg>Import the bench module<commit_after>extern crate hyper;
extern crate pbr;
extern crate ansi_term;

use std::sync::{Arc, Mutex};

#[macro_use]
pub mod logs;

pub mod authorization;
pub mod bench;
pub mod cargo_helper;
pub mod client;
pub mod contentlength;
pub mod download;
pub mod filesize;
pub mod http_version;
pub mod response;
pub mod util;
pub mod write;

/// Represents a number of bytes, as `u64`.
pub type Bytes = u64;
/// Represents a 'chunk', which is just a piece of bytes.
type Chunk = Vec<u8>;
/// Represents a list of chunks
pub type Chunks = Vec<Chunk>;
/// Represents a shared mutable reference of chunks
pub type SChunks = Arc<Mutex<Chunks>>;
/// Represents an URL
pub type URL<'a> = &'a str;
<|endoftext|>


<commit_before>//! QRCode encoder
//!
//! This crate provides a QR code and Micro QR code encoder for binary data.
//!
//!     use qrcode::QrCode;
//!
//!     let code = QrCode::new(b"Some content here.");
//!     match code {
//!         Err(err) => panic!("Failed to encode the QR code: {:?}", err),
//!         Ok(code) => {
//!             for y in (0 .. code.width()) {
//!                 for x in (0 .. code.width()) {
//!                     let color = if code[(x, y)] { "black" } else { "white" };
//!                     // render color at position (x, y)
//!                 }
//!             }
//!         }
//!     }
//!

#![unstable]
#![feature(slicing_syntax)]

#[allow(unstable)]
extern crate test;

use std::ops::Index;

pub use types::{QrResult, EcLevel, Version};

pub mod types;
pub mod bits;
pub mod optimize;
pub mod ec;
pub mod canvas;

/// The encoded QR code symbol.
#[derive(Clone)]
pub struct QrCode {
    content: Vec<bool>,
    version: Version,
    ec_level: EcLevel,
    width: usize,
}

impl QrCode {
    /// Constructs a new QR code which automatically encodes the given data.
    ///
    /// This method uses the "medium" error correction level and automatically
    /// chooses the smallest QR code.
    ///
    ///     use qrcode::QrCode;
    ///
    ///     let code = QrCode::new(b"Some data").unwrap();
    ///
    pub fn new(data: &[u8]) -> QrResult<QrCode> {
        QrCode::with_error_correction_level(data, EcLevel::M)
    }

    /// Constructs a new QR code which automatically encodes the given data at a
    /// specific error correction level.
    ///
    /// This method automatically chooses the smallest QR code.
    ///
    ///     use qrcode::{QrCode, EcLevel};
    ///
    ///     let code = QrCode::with_error_correction_level(b"Some data", EcLevel::H).unwrap();
    ///
    pub fn with_error_correction_level(data: &[u8], ec_level: EcLevel) -> QrResult<QrCode> {
        let bits = try!(bits::encode_auto(data, ec_level));
        QrCode::with_bits(bits, ec_level)
    }

    /// Constructs a new QR code for the given version and error correction
    /// level.
    ///
    ///     use qrcode::{QrCode, Version, EcLevel};
    ///
    ///     let code = QrCode::with_version(b"Some data", Version::Normal(5), EcLevel::M).unwrap();
    ///
    /// This method can also be used to generate Micro QR code.
    ///
    ///     use qrcode::{QrCode, Version, EcLevel};
    ///
    ///     let micro_code = QrCode::with_version(b"123", Version::Micro(1), EcLevel::L).unwrap();
    ///
    pub fn with_version(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<QrCode> {
        let mut bits = bits::Bits::new(version);
        try!(bits.push_optimal_data(data));
        try!(bits.push_terminator(ec_level));
        QrCode::with_bits(bits, ec_level)
    }

    /// Constructs a new QR code with encoded bits.
    ///
    /// Use this method only if there are very special need to manipulate the
    /// raw bits before encoding. Some examples are:
    ///
    /// * Encode data using specific character set with ECI
    /// * Use the FNC1 modes
    /// * Avoid the optimal segmentation algorithm
    ///
    /// See the `Bits` structure for detail.
    ///
    ///     #![allow(unused_must_use)]
    ///
    ///     use qrcode::{QrCode, Version, EcLevel};
    ///     use qrcode::bits::Bits;
    ///
    ///     let mut bits = Bits::new(Version::Normal(1));
    ///     bits.push_eci_designator(9);
    ///     bits.push_byte_data(b"\xca\xfe\xe4\xe9\xea\xe1\xf2 QR");
    ///     bits.push_terminator(EcLevel::L);
    ///     let qrcode = QrCode::with_bits(bits, EcLevel::L);
    ///
    pub fn with_bits(bits: bits::Bits, ec_level: EcLevel) -> QrResult<QrCode> {
        let version = bits.version();
        let data = bits.into_bytes();
        let (encoded_data, ec_data) = try!(ec::construct_codewords(&*data, version, ec_level));
        let mut canvas = canvas::Canvas::new(version, ec_level);
        canvas.draw_all_functional_patterns();
        canvas.draw_data(&*encoded_data, &*ec_data);
        let canvas = canvas.apply_best_mask();
        Ok(QrCode {
            content: canvas.to_bools(),
            version: version,
            ec_level: ec_level,
            width: version.width() as usize,
        })
    }

    /// Gets the version of this QR code.
    pub fn version(&self) -> Version {
        self.version
    }

    /// Gets the error correction level of this QR code.
    pub fn error_correction_level(&self) -> EcLevel {
        self.ec_level
    }

    /// Gets the number of modules per side, i.e. the width of this QR code.
    ///
    /// The width here does not contain the quiet zone paddings.
    pub fn width(&self) -> usize {
        self.width
    }

    /// Gets the maximum number of allowed erratic modules can be introduced
    /// before the data becomes corrupted. Note that errors should not be
    /// introduced to functional modules.
    pub fn max_allowed_errors(&self) -> usize {
        ec::max_allowed_errors(self.version, self.ec_level).unwrap()
    }

    /// Checks whether a module at coordinate (x, y) is a functional module or
    /// not.
    pub fn is_functional(&self, x: usize, y: usize) -> bool {
        canvas::is_functional(self.version, self.version.width(), x as i16, y as i16)
    }

    /// Converts the QR code into a human-readable string. This is mainly for
    /// debugging only.
    pub fn to_debug_str(&self, on_char: char, off_char: char) -> String {
        let width = self.width;
        let mut k = 0;
        let mut res = String::with_capacity(width * (width + 1));
        for _ in (0 .. width) {
            res.push('\n');
            for _ in (0 .. width) {
                res.push(if self.content[k] { on_char } else { off_char });
                k += 1;
            }
        }
        res
    }

    /// Converts the QR code to a vector of booleans. Each entry represents the
    /// color of the module, with "true" means dark and "false" means light.
    pub fn to_vec(&self) -> Vec<bool> {
        self.content.clone()
    }

    /// Converts the QR code to a vector of booleans. Each entry represents the
    /// color of the module, with "true" means dark and "false" means light.
    pub fn into_vec(self) -> Vec<bool> {
        self.content.clone()
    }
}

impl Index<(usize, usize)> for QrCode {
    type Output = bool;

    fn index(&self, &(x, y): &(usize, usize)) -> &bool {
        let index = y * self.width + x;
        &self.content[index]
    }
}

#[cfg(test)]
mod tests {
    use {QrCode, Version, EcLevel};

    #[test]
    fn test_annex_i_qr() {
        // This uses the ISO Annex I as test vector.
        let code = QrCode::with_version(b"01234567", Version::Normal(1), EcLevel::M).unwrap();
        assert_eq!(&*code.to_debug_str('#', '.'), "\n\
                    #######..#.##.#######\n\
                    #.....#..####.#.....#\n\
                    #.###.#.#.....#.###.#\n\
                    #.###.#.##....#.###.#\n\
                    #.###.#.#.###.#.###.#\n\
                    #.....#.#...#.#.....#\n\
                    #######.#.#.#.#######\n\
                    ........#..##........\n\
                    #.#####..#..#.#####..\n\
                    ...#.#.##.#.#..#.##..\n\
                    ..#...##.#.#.#..#####\n\
                    ....#....#.....####..\n\
                    ...######..#.#..#....\n\
                    ........#.#####..##..\n\
                    #######..##.#.##.....\n\
                    #.....#.#.#####...#.#\n\
                    #.###.#.#...#..#.##..\n\
                    #.###.#.##..#..#.....\n\
                    #.###.#.#.##.#..#.#..\n\
                    #.....#........##.##.\n\
                    #######.####.#..#.#..");
    }

    #[test]
    fn test_annex_i_micro_qr() {
        let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap();
        assert_eq!(&*code.to_debug_str('#', '.'), "\n\
                    #######.#.#.#\n\
                    #.....#.###.#\n\
                    #.###.#..##.#\n\
                    #.###.#..####\n\
                    #.###.#.###..\n\
                    #.....#.#...#\n\
                    #######..####\n\
                    .........##..\n\
                    ##.#....#...#\n\
                    .##.#.#.#.#.#\n\
                    ###..#######.\n\
                    ...#.#....##.\n\
                    ###.#..##.###");
    }
}

// Copyright 2014 Kenny Chan
//
// 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.

<commit_msg>rustup<commit_after>//! QRCode encoder
//!
//! This crate provides a QR code and Micro QR code encoder for binary data.
//!
//!     use qrcode::QrCode;
//!
//!     let code = QrCode::new(b"Some content here.");
//!     match code {
//!         Err(err) => panic!("Failed to encode the QR code: {:?}", err),
//!         Ok(code) => {
//!             for y in (0 .. code.width()) {
//!                 for x in (0 .. code.width()) {
//!                     let color = if code[(x, y)] { "black" } else { "white" };
//!                     // render color at position (x, y)
//!                 }
//!             }
//!         }
//!     }
//!

#![unstable]
#![feature(test, core)] // Unstable libraries

extern crate test;

use std::ops::Index;

pub use types::{QrResult, EcLevel, Version};

pub mod types;
pub mod bits;
pub mod optimize;
pub mod ec;
pub mod canvas;

/// The encoded QR code symbol.
#[derive(Clone)]
pub struct QrCode {
    content: Vec<bool>,
    version: Version,
    ec_level: EcLevel,
    width: usize,
}

impl QrCode {
    /// Constructs a new QR code which automatically encodes the given data.
    ///
    /// This method uses the "medium" error correction level and automatically
    /// chooses the smallest QR code.
    ///
    ///     use qrcode::QrCode;
    ///
    ///     let code = QrCode::new(b"Some data").unwrap();
    ///
    pub fn new(data: &[u8]) -> QrResult<QrCode> {
        QrCode::with_error_correction_level(data, EcLevel::M)
    }

    /// Constructs a new QR code which automatically encodes the given data at a
    /// specific error correction level.
    ///
    /// This method automatically chooses the smallest QR code.
    ///
    ///     use qrcode::{QrCode, EcLevel};
    ///
    ///     let code = QrCode::with_error_correction_level(b"Some data", EcLevel::H).unwrap();
    ///
    pub fn with_error_correction_level(data: &[u8], ec_level: EcLevel) -> QrResult<QrCode> {
        let bits = try!(bits::encode_auto(data, ec_level));
        QrCode::with_bits(bits, ec_level)
    }

    /// Constructs a new QR code for the given version and error correction
    /// level.
    ///
    ///     use qrcode::{QrCode, Version, EcLevel};
    ///
    ///     let code = QrCode::with_version(b"Some data", Version::Normal(5), EcLevel::M).unwrap();
    ///
    /// This method can also be used to generate Micro QR code.
    ///
    ///     use qrcode::{QrCode, Version, EcLevel};
    ///
    ///     let micro_code = QrCode::with_version(b"123", Version::Micro(1), EcLevel::L).unwrap();
    ///
    pub fn with_version(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<QrCode> {
        let mut bits = bits::Bits::new(version);
        try!(bits.push_optimal_data(data));
        try!(bits.push_terminator(ec_level));
        QrCode::with_bits(bits, ec_level)
    }

    /// Constructs a new QR code with encoded bits.
    ///
    /// Use this method only if there are very special need to manipulate the
    /// raw bits before encoding. Some examples are:
    ///
    /// * Encode data using specific character set with ECI
    /// * Use the FNC1 modes
    /// * Avoid the optimal segmentation algorithm
    ///
    /// See the `Bits` structure for detail.
    ///
    ///     #![allow(unused_must_use)]
    ///
    ///     use qrcode::{QrCode, Version, EcLevel};
    ///     use qrcode::bits::Bits;
    ///
    ///     let mut bits = Bits::new(Version::Normal(1));
    ///     bits.push_eci_designator(9);
    ///     bits.push_byte_data(b"\xca\xfe\xe4\xe9\xea\xe1\xf2 QR");
    ///     bits.push_terminator(EcLevel::L);
    ///     let qrcode = QrCode::with_bits(bits, EcLevel::L);
    ///
    pub fn with_bits(bits: bits::Bits, ec_level: EcLevel) -> QrResult<QrCode> {
        let version = bits.version();
        let data = bits.into_bytes();
        let (encoded_data, ec_data) = try!(ec::construct_codewords(&*data, version, ec_level));
        let mut canvas = canvas::Canvas::new(version, ec_level);
        canvas.draw_all_functional_patterns();
        canvas.draw_data(&*encoded_data, &*ec_data);
        let canvas = canvas.apply_best_mask();
        Ok(QrCode {
            content: canvas.to_bools(),
            version: version,
            ec_level: ec_level,
            width: version.width() as usize,
        })
    }

    /// Gets the version of this QR code.
    pub fn version(&self) -> Version {
        self.version
    }

    /// Gets the error correction level of this QR code.
    pub fn error_correction_level(&self) -> EcLevel {
        self.ec_level
    }

    /// Gets the number of modules per side, i.e. the width of this QR code.
    ///
    /// The width here does not contain the quiet zone paddings.
    pub fn width(&self) -> usize {
        self.width
    }

    /// Gets the maximum number of allowed erratic modules can be introduced
    /// before the data becomes corrupted. Note that errors should not be
    /// introduced to functional modules.
    pub fn max_allowed_errors(&self) -> usize {
        ec::max_allowed_errors(self.version, self.ec_level).unwrap()
    }

    /// Checks whether a module at coordinate (x, y) is a functional module or
    /// not.
    pub fn is_functional(&self, x: usize, y: usize) -> bool {
        canvas::is_functional(self.version, self.version.width(), x as i16, y as i16)
    }

    /// Converts the QR code into a human-readable string. This is mainly for
    /// debugging only.
    pub fn to_debug_str(&self, on_char: char, off_char: char) -> String {
        let width = self.width;
        let mut k = 0;
        let mut res = String::with_capacity(width * (width + 1));
        for _ in (0 .. width) {
            res.push('\n');
            for _ in (0 .. width) {
                res.push(if self.content[k] { on_char } else { off_char });
                k += 1;
            }
        }
        res
    }

    /// Converts the QR code to a vector of booleans. Each entry represents the
    /// color of the module, with "true" means dark and "false" means light.
    pub fn to_vec(&self) -> Vec<bool> {
        self.content.clone()
    }

    /// Converts the QR code to a vector of booleans. Each entry represents the
    /// color of the module, with "true" means dark and "false" means light.
    pub fn into_vec(self) -> Vec<bool> {
        self.content.clone()
    }
}

impl Index<(usize, usize)> for QrCode {
    type Output = bool;

    fn index(&self, &(x, y): &(usize, usize)) -> &bool {
        let index = y * self.width + x;
        &self.content[index]
    }
}

#[cfg(test)]
mod tests {
    use {QrCode, Version, EcLevel};

    #[test]
    fn test_annex_i_qr() {
        // This uses the ISO Annex I as test vector.
        let code = QrCode::with_version(b"01234567", Version::Normal(1), EcLevel::M).unwrap();
        assert_eq!(&*code.to_debug_str('#', '.'), "\n\
                    #######..#.##.#######\n\
                    #.....#..####.#.....#\n\
                    #.###.#.#.....#.###.#\n\
                    #.###.#.##....#.###.#\n\
                    #.###.#.#.###.#.###.#\n\
                    #.....#.#...#.#.....#\n\
                    #######.#.#.#.#######\n\
                    ........#..##........\n\
                    #.#####..#..#.#####..\n\
                    ...#.#.##.#.#..#.##..\n\
                    ..#...##.#.#.#..#####\n\
                    ....#....#.....####..\n\
                    ...######..#.#..#....\n\
                    ........#.#####..##..\n\
                    #######..##.#.##.....\n\
                    #.....#.#.#####...#.#\n\
                    #.###.#.#...#..#.##..\n\
                    #.###.#.##..#..#.....\n\
                    #.###.#.#.##.#..#.#..\n\
                    #.....#........##.##.\n\
                    #######.####.#..#.#..");
    }

    #[test]
    fn test_annex_i_micro_qr() {
        let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap();
        assert_eq!(&*code.to_debug_str('#', '.'), "\n\
                    #######.#.#.#\n\
                    #.....#.###.#\n\
                    #.###.#..##.#\n\
                    #.###.#..####\n\
                    #.###.#.###..\n\
                    #.....#.#...#\n\
                    #######..####\n\
                    .........##..\n\
                    ##.#....#...#\n\
                    .##.#.#.#.#.#\n\
                    ###..#######.\n\
                    ...#.#....##.\n\
                    ###.#..##.###");
    }
}

// Copyright 2014 Kenny Chan
//
// 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.

<|endoftext|>


<commit_before>/// Metadata on devices
pub mod devices;

/// Public-facing API
pub mod api;

/// Requests for specific devices
pub mod requests;

pub mod values;
<commit_msg>Introducing values<commit_after>/// Metadata on devices
pub mod devices;

/// Public-facing API
pub mod api;

/// Requests for specific devices
pub mod requests;

pub mod values;<|endoftext|>


<commit_before>//! # Overview
//!
//! This crate provides native rust implementations of image encoding and decoding as well as some
//! basic image manipulation functions. Additional documentation can currently also be found in the
//! [README.md file which is most easily viewed on
//! github](https://github.com/image-rs/image/blob/master/README.md).
//!
//! There are two core problems for which this library provides solutions: a unified interface for image
//! encodings and simple generic buffers for their content. It's possible to use either feature
//! without the other. The focus is on a small and stable set of common operations that can be
//! supplemented by other specialized crates. The library also prefers safe solutions with few
//! dependencies.
//!
//! # High level API
//!
//! Load images using [`io::Reader`]:
//!
//! ```rust,no_run
//! use std::io::Cursor;
//! use image::io::Reader as ImageReader;
//! # fn main() -> Result<(), image::ImageError> {
//! # let bytes = vec![0u8];
//!
//! let img = ImageReader::open("myimage.png")?.decode()?;
//! let img2 = ImageReader::new(Cursor::new(bytes)).with_guessed_format()?.decode()?;
//! # Ok(())
//! # }
//! ```
//!
//! And save them using [`save`] or [`write_to`] methods:
//!
//! ```rust,no_run
//! # use std::io::{Write, Cursor};
//! # use image::ImageOutputFormat;
//! # use image::DynamicImage;
//! # #[cfg(feature = "png")]
//! # fn main() -> Result<(), image::ImageError> {
//! # let img: DynamicImage = unimplemented!();
//! # let img2: DynamicImage = unimplemented!();
//! img.save("empty.jpg")?;
//!
//! let mut bytes: Vec<u8> = Vec::new();
//! img2.write_to(&mut Cursor::new(&mut bytes), image::ImageOutputFormat::Png)?;
//! # Ok(())
//! # }
//! # #[cfg(not(feature = "png"))] fn main() {}
//! ```
//!
//! With default features, the crate includes support for [many common image formats](codecs/index.html#supported-formats).
//!
//! [`save`]: enum.DynamicImage.html#method.save
//! [`write_to`]: enum.DynamicImage.html#method.write_to
//! [`io::Reader`]: io/struct.Reader.html
//!
//! # Image buffers
//!
//! The two main types for storing images:
//! * [`ImageBuffer`] which holds statically typed image contents.
//! * [`DynamicImage`] which is an enum over the supported ImageBuffer formats
//!     and supports conversions between them.
//!
//! As well as a few more specialized options:
//! * [`GenericImage`] trait for a mutable image buffer.
//! * [`GenericImageView`] trait for read only references to a GenericImage.
//! * [`flat`] module containing types for interoperability with generic channel
//!     matrices and foreign interfaces.
//!
//! [`GenericImageView`]: trait.GenericImageView.html
//! [`GenericImage`]: trait.GenericImage.html
//! [`ImageBuffer`]: struct.ImageBuffer.html
//! [`DynamicImage`]: enum.DynamicImage.html
//! [`flat`]: flat/index.html
//!
//! # Low level encoding/decoding API
//!
//! The [`ImageDecoder`] and [`ImageDecoderRect`] traits are implemented for many image file
//! formats. They decode image data by directly on raw byte slices. Given an ImageDecoder, you can
//! produce a DynamicImage via [`DynamicImage::from_decoder`].
//!
//! [`ImageEncoder`] provides the analogous functionality for encoding image data.
//!
//! [`DynamicImage::from_decoder`]: enum.DynamicImage.html#method.from_decoder
//! [`ImageDecoderRect`]: trait.ImageDecoderRect.html
//! [`ImageDecoder`]: trait.ImageDecoder.html
//! [`ImageEncoder`]: trait.ImageEncoder.html
#![warn(missing_docs)]
#![warn(unused_qualifications)]
#![deny(unreachable_pub)]
#![deny(deprecated)]
#![deny(missing_copy_implementations)]
#![cfg_attr(all(test, feature = "benchmarks"), feature(test))]
// it's a bit of a pain otherwise
#![allow(clippy::many_single_char_names)]
// it's a backwards compatibility break
#![allow(clippy::wrong_self_convention, clippy::enum_variant_names)]

#[cfg(all(test, feature = "benchmarks"))]
extern crate test;

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

pub use crate::color::{ColorType, ExtendedColorType};

pub use crate::color::{Luma, LumaA, Rgb, Rgba};

pub use crate::error::{ImageError, ImageResult};

pub use crate::image::{
    AnimationDecoder,
    GenericImage,
    GenericImageView,
    ImageDecoder,
    ImageDecoderRect,
    ImageEncoder,
    ImageFormat,
    ImageOutputFormat,
    // Iterators
    Pixels,
    Progress,
    SubImage,
};

pub use crate::buffer_::{
    GrayAlphaImage,
    GrayImage,
    // Image types
    ImageBuffer,
    Rgb32FImage,
    RgbImage,
    Rgba32FImage,
    RgbaImage,
};

pub use crate::flat::FlatSamples;

// Traits
pub use crate::traits::{EncodableLayout, Pixel, PixelWithColorType, Primitive};

// Opening and loading images
pub use crate::dynimage::{
    image_dimensions, load_from_memory, load_from_memory_with_format, open, save_buffer,
    save_buffer_with_format, write_buffer_with_format,
};
pub use crate::io::free_functions::{guess_format, load};

pub use crate::dynimage::DynamicImage;

pub use crate::animation::{Delay, Frame, Frames};

// More detailed error type
pub mod error;

/// Iterators and other auxiliary structure for the `ImageBuffer` type.
pub mod buffer {
    // Only those not exported at the top-level
    pub use crate::buffer_::{
        ConvertBuffer, EnumeratePixels, EnumeratePixelsMut, EnumerateRows, EnumerateRowsMut,
        Pixels, PixelsMut, Rows, RowsMut,
    };
}

// Math utils
pub mod math;

// Image processing functions
pub mod imageops;

// Io bindings
pub mod io;

// Buffer representations for ffi.
pub mod flat;

/// Encoding and decoding for various image file formats.
///
/// # Supported formats
///
/// | Format | Decoding | Encoding |
/// | ------ | -------- | -------- |
/// | PNG    | All supported color types | Same as decoding |
/// | JPEG   | Baseline and progressive | Baseline JPEG |
/// | GIF    | Yes | Yes |
/// | BMP    | Yes | Rgb8, Rgba8, Gray8, GrayA8 |
/// | ICO    | Yes | Yes |
/// | TIFF   | Baseline(no fax support) + LZW + PackBits | Rgb8, Rgba8, Gray8 |
/// | WebP   | Lossy(Luma channel only) | No |
/// | AVIF   | Only 8-bit | Lossy |
/// | PNM    | PBM, PGM, PPM, standard PAM | Yes |
/// | DDS    | DXT1, DXT3, DXT5 | No |
/// | TGA    | Yes | Rgb8, Rgba8, Bgr8, Bgra8, Gray8, GrayA8 |
/// | OpenEXR  | Rgb32F, Rgba32F (no dwa compression) | Rgb32F, Rgba32F (no dwa compression) |
/// | farbfeld | Yes | Yes |
///
/// ## A note on format specific features
///
/// One of the main goals of `image` is stability, in runtime but also for programmers. This
/// ensures that performance as well as safety fixes reach a majority of its user base with little
/// effort. Re-exporting all details of its dependencies would run counter to this goal as it
/// linked _all_ major version bumps between them and `image`. As such, we are wary of exposing too
/// many details, or configuration options, that are not shared between different image formats.
///
/// Nevertheless, the advantage of precise control is hard to ignore. We will thus consider
/// _wrappers_, not direct re-exports, in either of the following cases:
///
/// 1. A standard specifies that configuration _x_ is required for decoders/encoders and there
///    exists an essentially canonical way to control it.
/// 2. At least two different implementations agree on some (sub-)set of features in practice.
/// 3. A technical argument including measurements of the performance, space benefits, or otherwise
///    objectively quantified benefits can be made, and the added interface is unlikely to require
///    breaking changes.
///
/// Features that fulfill two or more criteria are preferred.
///
/// Re-exports of dependencies that reach version `1` will be discussed when it happens.
pub mod codecs {
    #[cfg(any(feature = "avif-encoder", feature = "avif-decoder"))]
    pub mod avif;
    #[cfg(feature = "bmp")]
    pub mod bmp;
    #[cfg(feature = "dds")]
    pub mod dds;
    #[cfg(feature = "dxt")]
    #[deprecated = "DXT support will be removed in a future version. See https://github.com/image-rs/image/issues/1623"]
    pub mod dxt;
    #[cfg(feature = "farbfeld")]
    pub mod farbfeld;
    #[cfg(feature = "gif")]
    pub mod gif;
    #[cfg(feature = "hdr")]
    pub mod hdr;
    #[cfg(feature = "ico")]
    pub mod ico;
    #[cfg(feature = "jpeg")]
    pub mod jpeg;
    #[cfg(feature = "openexr")]
    pub mod openexr;
    #[cfg(feature = "png")]
    pub mod png;
    #[cfg(feature = "pnm")]
    pub mod pnm;
    #[cfg(feature = "tga")]
    pub mod tga;
    #[cfg(feature = "tiff")]
    pub mod tiff;
    #[cfg(feature = "webp")]
    pub mod webp;
}

mod animation;
#[path = "buffer.rs"]
mod buffer_;
mod color;
mod dynimage;
mod image;
mod traits;
mod utils;

// Can't use the macro-call itself within the `doc` attribute. So force it to eval it as part of
// the macro invocation.
//
// The inspiration for the macro and implementation is from
// <https://github.com/GuillaumeGomez/doc-comment>
//
// MIT License
//
// Copyright (c) 2018 Guillaume Gomez
macro_rules! insert_as_doc {
    { $content:expr } => {
        #[doc = $content] extern { }
    }
}

// Provides the README.md as doc, to ensure the example works!
insert_as_doc!(include_str!("../README.md"));
<commit_msg>Update deprecation note<commit_after>//! # Overview
//!
//! This crate provides native rust implementations of image encoding and decoding as well as some
//! basic image manipulation functions. Additional documentation can currently also be found in the
//! [README.md file which is most easily viewed on
//! github](https://github.com/image-rs/image/blob/master/README.md).
//!
//! There are two core problems for which this library provides solutions: a unified interface for image
//! encodings and simple generic buffers for their content. It's possible to use either feature
//! without the other. The focus is on a small and stable set of common operations that can be
//! supplemented by other specialized crates. The library also prefers safe solutions with few
//! dependencies.
//!
//! # High level API
//!
//! Load images using [`io::Reader`]:
//!
//! ```rust,no_run
//! use std::io::Cursor;
//! use image::io::Reader as ImageReader;
//! # fn main() -> Result<(), image::ImageError> {
//! # let bytes = vec![0u8];
//!
//! let img = ImageReader::open("myimage.png")?.decode()?;
//! let img2 = ImageReader::new(Cursor::new(bytes)).with_guessed_format()?.decode()?;
//! # Ok(())
//! # }
//! ```
//!
//! And save them using [`save`] or [`write_to`] methods:
//!
//! ```rust,no_run
//! # use std::io::{Write, Cursor};
//! # use image::ImageOutputFormat;
//! # use image::DynamicImage;
//! # #[cfg(feature = "png")]
//! # fn main() -> Result<(), image::ImageError> {
//! # let img: DynamicImage = unimplemented!();
//! # let img2: DynamicImage = unimplemented!();
//! img.save("empty.jpg")?;
//!
//! let mut bytes: Vec<u8> = Vec::new();
//! img2.write_to(&mut Cursor::new(&mut bytes), image::ImageOutputFormat::Png)?;
//! # Ok(())
//! # }
//! # #[cfg(not(feature = "png"))] fn main() {}
//! ```
//!
//! With default features, the crate includes support for [many common image formats](codecs/index.html#supported-formats).
//!
//! [`save`]: enum.DynamicImage.html#method.save
//! [`write_to`]: enum.DynamicImage.html#method.write_to
//! [`io::Reader`]: io/struct.Reader.html
//!
//! # Image buffers
//!
//! The two main types for storing images:
//! * [`ImageBuffer`] which holds statically typed image contents.
//! * [`DynamicImage`] which is an enum over the supported ImageBuffer formats
//!     and supports conversions between them.
//!
//! As well as a few more specialized options:
//! * [`GenericImage`] trait for a mutable image buffer.
//! * [`GenericImageView`] trait for read only references to a GenericImage.
//! * [`flat`] module containing types for interoperability with generic channel
//!     matrices and foreign interfaces.
//!
//! [`GenericImageView`]: trait.GenericImageView.html
//! [`GenericImage`]: trait.GenericImage.html
//! [`ImageBuffer`]: struct.ImageBuffer.html
//! [`DynamicImage`]: enum.DynamicImage.html
//! [`flat`]: flat/index.html
//!
//! # Low level encoding/decoding API
//!
//! The [`ImageDecoder`] and [`ImageDecoderRect`] traits are implemented for many image file
//! formats. They decode image data by directly on raw byte slices. Given an ImageDecoder, you can
//! produce a DynamicImage via [`DynamicImage::from_decoder`].
//!
//! [`ImageEncoder`] provides the analogous functionality for encoding image data.
//!
//! [`DynamicImage::from_decoder`]: enum.DynamicImage.html#method.from_decoder
//! [`ImageDecoderRect`]: trait.ImageDecoderRect.html
//! [`ImageDecoder`]: trait.ImageDecoder.html
//! [`ImageEncoder`]: trait.ImageEncoder.html
#![warn(missing_docs)]
#![warn(unused_qualifications)]
#![deny(unreachable_pub)]
#![deny(deprecated)]
#![deny(missing_copy_implementations)]
#![cfg_attr(all(test, feature = "benchmarks"), feature(test))]
// it's a bit of a pain otherwise
#![allow(clippy::many_single_char_names)]
// it's a backwards compatibility break
#![allow(clippy::wrong_self_convention, clippy::enum_variant_names)]

#[cfg(all(test, feature = "benchmarks"))]
extern crate test;

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

pub use crate::color::{ColorType, ExtendedColorType};

pub use crate::color::{Luma, LumaA, Rgb, Rgba};

pub use crate::error::{ImageError, ImageResult};

pub use crate::image::{
    AnimationDecoder,
    GenericImage,
    GenericImageView,
    ImageDecoder,
    ImageDecoderRect,
    ImageEncoder,
    ImageFormat,
    ImageOutputFormat,
    // Iterators
    Pixels,
    Progress,
    SubImage,
};

pub use crate::buffer_::{
    GrayAlphaImage,
    GrayImage,
    // Image types
    ImageBuffer,
    Rgb32FImage,
    RgbImage,
    Rgba32FImage,
    RgbaImage,
};

pub use crate::flat::FlatSamples;

// Traits
pub use crate::traits::{EncodableLayout, Pixel, PixelWithColorType, Primitive};

// Opening and loading images
pub use crate::dynimage::{
    image_dimensions, load_from_memory, load_from_memory_with_format, open, save_buffer,
    save_buffer_with_format, write_buffer_with_format,
};
pub use crate::io::free_functions::{guess_format, load};

pub use crate::dynimage::DynamicImage;

pub use crate::animation::{Delay, Frame, Frames};

// More detailed error type
pub mod error;

/// Iterators and other auxiliary structure for the `ImageBuffer` type.
pub mod buffer {
    // Only those not exported at the top-level
    pub use crate::buffer_::{
        ConvertBuffer, EnumeratePixels, EnumeratePixelsMut, EnumerateRows, EnumerateRowsMut,
        Pixels, PixelsMut, Rows, RowsMut,
    };
}

// Math utils
pub mod math;

// Image processing functions
pub mod imageops;

// Io bindings
pub mod io;

// Buffer representations for ffi.
pub mod flat;

/// Encoding and decoding for various image file formats.
///
/// # Supported formats
///
/// | Format | Decoding | Encoding |
/// | ------ | -------- | -------- |
/// | PNG    | All supported color types | Same as decoding |
/// | JPEG   | Baseline and progressive | Baseline JPEG |
/// | GIF    | Yes | Yes |
/// | BMP    | Yes | Rgb8, Rgba8, Gray8, GrayA8 |
/// | ICO    | Yes | Yes |
/// | TIFF   | Baseline(no fax support) + LZW + PackBits | Rgb8, Rgba8, Gray8 |
/// | WebP   | Lossy(Luma channel only) | No |
/// | AVIF   | Only 8-bit | Lossy |
/// | PNM    | PBM, PGM, PPM, standard PAM | Yes |
/// | DDS    | DXT1, DXT3, DXT5 | No |
/// | TGA    | Yes | Rgb8, Rgba8, Bgr8, Bgra8, Gray8, GrayA8 |
/// | OpenEXR  | Rgb32F, Rgba32F (no dwa compression) | Rgb32F, Rgba32F (no dwa compression) |
/// | farbfeld | Yes | Yes |
///
/// ## A note on format specific features
///
/// One of the main goals of `image` is stability, in runtime but also for programmers. This
/// ensures that performance as well as safety fixes reach a majority of its user base with little
/// effort. Re-exporting all details of its dependencies would run counter to this goal as it
/// linked _all_ major version bumps between them and `image`. As such, we are wary of exposing too
/// many details, or configuration options, that are not shared between different image formats.
///
/// Nevertheless, the advantage of precise control is hard to ignore. We will thus consider
/// _wrappers_, not direct re-exports, in either of the following cases:
///
/// 1. A standard specifies that configuration _x_ is required for decoders/encoders and there
///    exists an essentially canonical way to control it.
/// 2. At least two different implementations agree on some (sub-)set of features in practice.
/// 3. A technical argument including measurements of the performance, space benefits, or otherwise
///    objectively quantified benefits can be made, and the added interface is unlikely to require
///    breaking changes.
///
/// Features that fulfill two or more criteria are preferred.
///
/// Re-exports of dependencies that reach version `1` will be discussed when it happens.
pub mod codecs {
    #[cfg(any(feature = "avif-encoder", feature = "avif-decoder"))]
    pub mod avif;
    #[cfg(feature = "bmp")]
    pub mod bmp;
    #[cfg(feature = "dds")]
    pub mod dds;
    #[cfg(feature = "dxt")]
    #[deprecated = "DXT support will be removed or reworked in a future version. Prefer the `squish` crate instead. See https://github.com/image-rs/image/issues/1623"]
    pub mod dxt;
    #[cfg(feature = "farbfeld")]
    pub mod farbfeld;
    #[cfg(feature = "gif")]
    pub mod gif;
    #[cfg(feature = "hdr")]
    pub mod hdr;
    #[cfg(feature = "ico")]
    pub mod ico;
    #[cfg(feature = "jpeg")]
    pub mod jpeg;
    #[cfg(feature = "openexr")]
    pub mod openexr;
    #[cfg(feature = "png")]
    pub mod png;
    #[cfg(feature = "pnm")]
    pub mod pnm;
    #[cfg(feature = "tga")]
    pub mod tga;
    #[cfg(feature = "tiff")]
    pub mod tiff;
    #[cfg(feature = "webp")]
    pub mod webp;
}

mod animation;
#[path = "buffer.rs"]
mod buffer_;
mod color;
mod dynimage;
mod image;
mod traits;
mod utils;

// Can't use the macro-call itself within the `doc` attribute. So force it to eval it as part of
// the macro invocation.
//
// The inspiration for the macro and implementation is from
// <https://github.com/GuillaumeGomez/doc-comment>
//
// MIT License
//
// Copyright (c) 2018 Guillaume Gomez
macro_rules! insert_as_doc {
    { $content:expr } => {
        #[doc = $content] extern { }
    }
}

// Provides the README.md as doc, to ensure the example works!
insert_as_doc!(include_str!("../README.md"));
<|endoftext|>