<commit_before>use luminance::{Depth32F, Dim2, Flat, Framebuffer, Mode, RGBA32F, Tess, Texture, Uniform, Unit};
use luminance::pipeline::{Pipe, Pipeline, RenderCommand, ShadingCommand};
use luminance::tess::TessRender;
use std::ops::{Add, Sub, Mul};

pub use luminance::{Equation, Factor};

use resource::Res;
use scene::Scene;
use shader::Program;

/// Simple texture that can be embedded into a compositing graph.
pub type TextureLayer<'a> = &'a ColorMap;

pub type ColorMap = Texture<Flat, Dim2, RGBA32F>;
pub type DepthMap = Texture<Flat, Dim2, Depth32F>;

/// Render layer used to host renders.
pub struct RenderLayer<'a> {
  render: Box<Fn(&Framebuffer<Flat, Dim2, ColorMap, DepthMap>) + 'a>
}

impl<'a> RenderLayer<'a> {
  pub fn new<F>(render: F) -> Self where F: 'a + Fn(&Framebuffer<Flat, Dim2, ColorMap, DepthMap>) {
    RenderLayer {
      render: Box::new(render)
    }
  }
}

/// Compositing node.
pub enum Node<'a> {
  /// A render node.
  ///
  /// Contains render layer.
  Render(RenderLayer<'a>),
  /// A texture node.
  ///
  /// Contains a single texture.
  Texture(TextureLayer<'a>),
  /// Composite node.
  ///
  /// Composite nodes are used to blend two compositing nodes according to a given `Equation` and
  /// two blending `Factor`s for source and destination, respectively.
  Composite(Box<Node<'a>>, Box<Node<'a>>, Equation, Factor, Factor)
}

impl<'a> Node<'a> {
  /// Compose this node with another one.
  pub fn compose_with(self, other: Self, eq: Equation, src_fct: Factor, dst_fct: Factor) -> Self {
    Node::Composite(Box::new(self), Box::new(other), eq, src_fct, dst_fct)
  }
}

impl<'a> From<RenderLayer<'a>> for Node<'a> {
  fn from(layer: RenderLayer<'a>) -> Self {
    Node::Render(layer)
  }
}

impl<'a> From<TextureLayer<'a>> for Node<'a> {
  fn from(texture: TextureLayer<'a>) -> Self {
    Node::Texture(texture)
  }
}

impl<'a> Add for Node<'a> {
  type Output = Self;

  fn add(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::One, Factor::One)
  }
}

impl<'a> Sub for Node<'a> {
  type Output = Self;

  fn sub(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Subtract, Factor::One, Factor::One)
  }
}

impl<'a> Mul for Node<'a> {
  type Output = Self;

  fn mul(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::Zero, Factor::SrcColor)
  }
}

/// Compositor object; used to consume `Node`s and output to screen.
pub struct Compositor {
  // width
  w: u32,
  // height
  h: u32,
  // allocated framebuffers that might contain nodes’ output
  framebuffers: Vec<Framebuffer<Flat, Dim2, ColorMap, DepthMap>>,
  // free list of available framebuffers
  free_framebuffers: Vec<usize>,
  // program used to compose nodes
  program: Res<Program>,
  // attributeless fullscreen quad for compositing
  quad: Tess
}

const FORWARD_SOURCE: &'static Uniform<Unit> = &Uniform::new(0);

impl Compositor {
  pub fn new(w: u32, h: u32, scene: &mut Scene) -> Self {
    Compositor {
      w: w,
      h: h,
      framebuffers: Vec::new(),
      free_framebuffers: Vec::new(),
      program: scene.get("spectra/compositing/forward.glsl", vec![FORWARD_SOURCE.sem("source")]).unwrap(),
      quad: Tess::attributeless(Mode::TriangleStrip, 4)
    }
  }

  /// Whenever a node must be composed, we need a framebuffer to render into. This function pulls a
  /// framebuffer to use (via self.framebuffers) by returing an index. It might allocate a new
  /// framebuffer if there isn’t enough framebuffers to be pulled.
  fn pull_framebuffer(&mut self) -> usize {
    self.free_framebuffers.pop().unwrap_or_else(|| {
      let framebuffer_index = self.framebuffers.len();

      let framebuffer = Framebuffer::new((self.w, self.h), 0).unwrap();
      self.framebuffers.push(framebuffer);

      framebuffer_index
    })
  }

  /// Whenever a node has finished being composed, we *might* need to dispose the framebuffer it has
  /// pulled. This funciton does that job.
  ///
  /// It never deallocates memory. It has an important property: once a framebuffer is pulled,
  /// calling that function will make it available for other nodes, improving memory usage for the
  /// next calls.
  #[inline]
  fn dispose_framebuffer(&mut self, framebuffer_index: usize) {
    self.free_framebuffers.push(framebuffer_index);
  }

  /// Consume and display a compositing graph represented by its nodes.
  pub fn display(&mut self, root: Node) {
    let fb_index = self.treat_node(root);

    {
      let fb = &self.framebuffers[fb_index];

      let screen = Framebuffer::default((self.w, self.h));

      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
      let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[&*fb.color_slot];

      Pipeline::new(&screen, black, texture_set, &[], shd_cmd).run();
    }

    self.dispose_framebuffer(fb_index);
    assert!(self.free_framebuffers.is_empty());
  }

  /// Treat a node hierarchy and return the index  of the framebuffer that contains the result.
  fn treat_node(&mut self, node: Node) -> usize {
    match node {
      Node::Render(layer) => self.render(layer),
      Node::Texture(texture) => self.texturize(texture),
      Node::Composite(left, right, eq, src_fct, dst_fct) => self.composite(*left, *right, eq, src_fct, dst_fct),
    }
  }

  fn render(&mut self, layer: RenderLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    (layer.render)(&fb);

    fb_index
  }

  fn texturize(&mut self, texture: TextureLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let black = [0., 0., 0., 1.];
    let program = self.program.borrow();
    let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
    let tess_render = TessRender::from(&self.quad);
    let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
    let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
    let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
    let texture_set = &[&**texture];

    Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();

    fb_index
  }

  fn composite(&mut self, left: Node, right: Node, eq: Equation, src_fct: Factor, dst_fct: Factor) -> usize {
    let left_index = self.treat_node(left);
    let right_index = self.treat_node(right);

    assert!(left_index < self.framebuffers.len());
    assert!(right_index < self.framebuffers.len());

    let fb_index = self.pull_framebuffer();

    {
      let fb = &self.framebuffers[fb_index];

      let left_fb = &self.framebuffers[left_index];
      let right_fb = &self.framebuffers[right_index];

      // compose
      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_left = [FORWARD_SOURCE.alter(Unit::new(0))];
      let uniforms_right = [FORWARD_SOURCE.alter(Unit::new(1))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[
        Pipe::empty().uniforms(&uniforms_left).unwrap(tess_render.clone()),
        Pipe::empty().uniforms(&uniforms_right).unwrap(tess_render)
      ];
      let render_cmd = &[Pipe::new(RenderCommand::new(Some((eq, src_fct, dst_fct)), false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[
        &*left_fb.color_slot,
        &*right_fb.color_slot
      ];

      Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();
    }

    // dispose both left and right framebuffers
    self.dispose_framebuffer(left_index);
    self.dispose_framebuffer(right_index);

    fb_index
  }
}
<commit_msg>Added Node::Color.<commit_after>use luminance::{Depth32F, Dim2, Flat, Framebuffer, Mode, RGBA32F, Tess, Texture, Uniform, Unit};
use luminance::pipeline::{Pipe, Pipeline, RenderCommand, ShadingCommand};
use luminance::tess::TessRender;
use std::ops::{Add, Sub, Mul};

pub use luminance::{Equation, Factor};

use color::ColorAlpha;
use resource::Res;
use scene::Scene;
use shader::Program;

/// Simple texture that can be embedded into a compositing graph.
pub type TextureLayer<'a> = &'a ColorMap;

pub type ColorMap = Texture<Flat, Dim2, RGBA32F>;
pub type DepthMap = Texture<Flat, Dim2, Depth32F>;

/// Render layer used to host renders.
pub struct RenderLayer<'a> {
  render: Box<Fn(&Framebuffer<Flat, Dim2, ColorMap, DepthMap>) + 'a>
}

impl<'a> RenderLayer<'a> {
  pub fn new<F>(render: F) -> Self where F: 'a + Fn(&Framebuffer<Flat, Dim2, ColorMap, DepthMap>) {
    RenderLayer {
      render: Box::new(render)
    }
  }
}

/// Compositing node.
pub enum Node<'a> {
  /// A render node.
  ///
  /// Contains render layer.
  Render(RenderLayer<'a>),
  /// A texture node.
  ///
  /// Contains a single texture.
  Texture(TextureLayer<'a>),
  /// A single color.
  Color(ColorAlpha),
  /// Composite node.
  ///
  /// Composite nodes are used to blend two compositing nodes according to a given `Equation` and
  /// two blending `Factor`s for source and destination, respectively.
  Composite(Box<Node<'a>>, Box<Node<'a>>, Equation, Factor, Factor)
}

impl<'a> Node<'a> {
  /// Compose this node with another one.
  pub fn compose_with(self, other: Self, eq: Equation, src_fct: Factor, dst_fct: Factor) -> Self {
    Node::Composite(Box::new(self), Box::new(other), eq, src_fct, dst_fct)
  }
}

impl<'a> From<RenderLayer<'a>> for Node<'a> {
  fn from(layer: RenderLayer<'a>) -> Self {
    Node::Render(layer)
  }
}

impl<'a> From<TextureLayer<'a>> for Node<'a> {
  fn from(texture: TextureLayer<'a>) -> Self {
    Node::Texture(texture)
  }
}

impl<'a> Add for Node<'a> {
  type Output = Self;

  fn add(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::One, Factor::One)
  }
}

impl<'a> Sub for Node<'a> {
  type Output = Self;

  fn sub(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Subtract, Factor::One, Factor::One)
  }
}

impl<'a> Mul for Node<'a> {
  type Output = Self;

  fn mul(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::Zero, Factor::SrcColor)
  }
}

/// Compositor object; used to consume `Node`s and output to screen.
pub struct Compositor {
  // width
  w: u32,
  // height
  h: u32,
  // allocated framebuffers that might contain nodes’ output
  framebuffers: Vec<Framebuffer<Flat, Dim2, ColorMap, DepthMap>>,
  // free list of available framebuffers
  free_framebuffers: Vec<usize>,
  // program used to compose nodes
  program: Res<Program>,
  // attributeless fullscreen quad for compositing
  quad: Tess
}

const FORWARD_SOURCE: &'static Uniform<Unit> = &Uniform::new(0);

impl Compositor {
  pub fn new(w: u32, h: u32, scene: &mut Scene) -> Self {
    Compositor {
      w: w,
      h: h,
      framebuffers: Vec::new(),
      free_framebuffers: Vec::new(),
      program: scene.get("spectra/compositing/forward.glsl", vec![FORWARD_SOURCE.sem("source")]).unwrap(),
      quad: Tess::attributeless(Mode::TriangleStrip, 4)
    }
  }

  /// Whenever a node must be composed, we need a framebuffer to render into. This function pulls a
  /// framebuffer to use (via self.framebuffers) by returing an index. It might allocate a new
  /// framebuffer if there isn’t enough framebuffers to be pulled.
  fn pull_framebuffer(&mut self) -> usize {
    self.free_framebuffers.pop().unwrap_or_else(|| {
      let framebuffer_index = self.framebuffers.len();

      let framebuffer = Framebuffer::new((self.w, self.h), 0).unwrap();
      self.framebuffers.push(framebuffer);

      framebuffer_index
    })
  }

  /// Whenever a node has finished being composed, we *might* need to dispose the framebuffer it has
  /// pulled. This funciton does that job.
  ///
  /// It never deallocates memory. It has an important property: once a framebuffer is pulled,
  /// calling that function will make it available for other nodes, improving memory usage for the
  /// next calls.
  #[inline]
  fn dispose_framebuffer(&mut self, framebuffer_index: usize) {
    self.free_framebuffers.push(framebuffer_index);
  }

  /// Consume and display a compositing graph represented by its nodes.
  pub fn display(&mut self, root: Node) {
    let fb_index = self.treat_node(root);

    {
      let fb = &self.framebuffers[fb_index];

      let screen = Framebuffer::default((self.w, self.h));

      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
      let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[&*fb.color_slot];

      Pipeline::new(&screen, black, texture_set, &[], shd_cmd).run();
    }

    self.dispose_framebuffer(fb_index);
    assert!(self.free_framebuffers.is_empty());
  }

  /// Treat a node hierarchy and return the index  of the framebuffer that contains the result.
  fn treat_node(&mut self, node: Node) -> usize {
    match node {
      Node::Render(layer) => self.render(layer),
      Node::Texture(texture) => self.texturize(texture),
      Node::Color(color) => self.colorize(color),
      Node::Composite(left, right, eq, src_fct, dst_fct) => self.composite(*left, *right, eq, src_fct, dst_fct),
    }
  }

  fn render(&mut self, layer: RenderLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    (layer.render)(&fb);

    fb_index
  }

  fn texturize(&mut self, texture: TextureLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let black = [0., 0., 0., 1.];
    let program = self.program.borrow();
    let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
    let tess_render = TessRender::from(&self.quad);
    let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
    let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
    let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
    let texture_set = &[&**texture];

    Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();

    fb_index
  }

  fn colorize(&mut self, color: ColorAlpha) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let color = *color.as_ref();

    Pipeline::new(fb, color, &[], &[], &[]).run();

    fb_index
  }

  fn composite(&mut self, left: Node, right: Node, eq: Equation, src_fct: Factor, dst_fct: Factor) -> usize {
    let left_index = self.treat_node(left);
    let right_index = self.treat_node(right);

    assert!(left_index < self.framebuffers.len());
    assert!(right_index < self.framebuffers.len());

    let fb_index = self.pull_framebuffer();

    {
      let fb = &self.framebuffers[fb_index];

      let left_fb = &self.framebuffers[left_index];
      let right_fb = &self.framebuffers[right_index];

      // compose
      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_left = [FORWARD_SOURCE.alter(Unit::new(0))];
      let uniforms_right = [FORWARD_SOURCE.alter(Unit::new(1))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[
        Pipe::empty().uniforms(&uniforms_left).unwrap(tess_render.clone()),
        Pipe::empty().uniforms(&uniforms_right).unwrap(tess_render)
      ];
      let render_cmd = &[Pipe::new(RenderCommand::new(Some((eq, src_fct, dst_fct)), false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[
        &*left_fb.color_slot,
        &*right_fb.color_slot
      ];

      Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();
    }

    // dispose both left and right framebuffers
    self.dispose_framebuffer(left_index);
    self.dispose_framebuffer(right_index);

    fb_index
  }
}
<|endoftext|>


<commit_before>use luminance::{Depth32F, Dim2, Flat, Framebuffer, Mode, RGBA32F, Tess, Texture, Uniform, Unit};
use luminance::pipeline::{Pipe, Pipeline, RenderCommand, ShadingCommand};
use luminance::tess::TessRender;
use std::ops::{Add, Mul, Sub};

pub use luminance::{Equation, Factor};

use color::ColorAlpha;
use resource::{Res, ResCache};
use shader::Program;

/// Simple texture that can be embedded into a compositing graph.
pub type TextureLayer<'a> = &'a ColorMap;

pub type ColorMap = Texture<Flat, Dim2, RGBA32F>;
pub type DepthMap = Texture<Flat, Dim2, Depth32F>;

/// Render layer used to host renders.
pub struct RenderLayer<'a> {
  render: Box<Fn(&Framebuffer<Flat, Dim2, ColorMap, DepthMap>) + 'a>
}

impl<'a> RenderLayer<'a> {
  pub fn new<F>(render: F) -> Self where F: 'a + Fn(&Framebuffer<Flat, Dim2, ColorMap, DepthMap>) {
    RenderLayer {
      render: Box::new(render)
    }
  }
}

/// Compositing node.
pub enum Node<'a> {
  /// A render node.
  ///
  /// Contains render layer.
  Render(RenderLayer<'a>),
  /// A texture node.
  ///
  /// Contains a single texture.
  Texture(TextureLayer<'a>),
  /// A single color.
  ///
  /// Keep in mind that such a node is great when you want to display a fullscreen colored quad but
  /// you shouldn’t use it for blending purpose. Adding color masking to your post-process is a
  /// better alternative and will avoid fillrate alteration.
  Color(ColorAlpha),
  /// Composite node.
  ///
  /// Composite nodes are used to blend two compositing nodes according to a given `Equation` and
  /// two blending `Factor`s for source and destination, respectively.
  Composite(Box<Node<'a>>, Box<Node<'a>>, ColorAlpha, Equation, Factor, Factor)
}

impl<'a> Node<'a> {
  /// Compose this node with another one.
  pub fn compose_with(self, rhs: Self, clear_color: ColorAlpha, eq: Equation, src_fct: Factor, dst_fct: Factor) -> Self {
    Node::Composite(Box::new(self), Box::new(rhs), clear_color, eq, src_fct, dst_fct)
  }

  /// Compose this node over the other. In effect, the resulting node will replace any pixels covered
  /// by the right node by the ones of the left node unless the alpha value is different than `1`.
  /// In that case, an additive blending based on the alpha value of the left node will be performed.
  ///
  /// If you set the alpha value to `0` at a pixel in the left node, then the resulting pixel will be
  /// the one from the right node.
  pub fn over(self, rhs: Self) -> Self {
    self.compose_with(rhs, ColorAlpha::new(0., 0., 0., 0.), Equation::Additive, Factor::SrcAlpha, Factor::SrcAlphaComplement)
  }
}

impl<'a> From<RenderLayer<'a>> for Node<'a> {
  fn from(layer: RenderLayer<'a>) -> Self {
    Node::Render(layer)
  }
}

impl<'a> From<TextureLayer<'a>> for Node<'a> {
  fn from(texture: TextureLayer<'a>) -> Self {
    Node::Texture(texture)
  }
}

impl<'a> From<ColorAlpha> for Node<'a> {
  fn from(color: ColorAlpha) -> Self {
    Node::Color(color)
  }
}

impl<'a> Add for Node<'a> {
  type Output = Self;

  fn add(self, rhs: Self) -> Self {
    self.compose_with(rhs, ColorAlpha::new(0., 0., 0., 0.), Equation::Additive, Factor::One, Factor::One)
  }
}

impl<'a> Sub for Node<'a> {
  type Output = Self;

  fn sub(self, rhs: Self) -> Self {
    self.compose_with(rhs, ColorAlpha::new(0., 0., 0., 0.), Equation::Subtract, Factor::One, Factor::One)
  }
}

impl<'a> Mul for Node<'a> {
  type Output = Self;

  fn mul(self, rhs: Self) -> Self {
    self.compose_with(rhs, ColorAlpha::new(1., 1., 1., 1.), Equation::Additive, Factor::Zero, Factor::SrcColor)
  }
}

/// Compositor object; used to consume `Node`s and output to screen.
pub struct Compositor {
  // width
  w: u32,
  // height
  h: u32,
  // allocated framebuffers that might contain nodes’ output
  framebuffers: Vec<Framebuffer<Flat, Dim2, ColorMap, DepthMap>>,
  // free list of available framebuffers
  free_framebuffers: Vec<usize>,
  // program used to compose nodes
  program: Res<Program>,
  // attributeless fullscreen quad for compositing
  quad: Tess
}

const FORWARD_SOURCE: &'static Uniform<Unit> = &Uniform::new(0);

impl Compositor {
  pub fn new(w: u32, h: u32, cache: &mut ResCache) -> Self {
    Compositor {
      w: w,
      h: h,
      framebuffers: Vec::new(),
      free_framebuffers: Vec::new(),
      program: cache.get("spectra/compositing/forward.glsl", vec![FORWARD_SOURCE.sem("source")]).unwrap(),
      quad: Tess::attributeless(Mode::TriangleStrip, 4)
    }
  }

  /// Whenever a node must be composed, we need a framebuffer to render into. This function pulls a
  /// framebuffer to use (via self.framebuffers) by returing an index. It might allocate a new
  /// framebuffer if there isn’t enough framebuffers to be pulled.
  fn pull_framebuffer(&mut self) -> usize {
    self.free_framebuffers.pop().unwrap_or_else(|| {
      let framebuffer_index = self.framebuffers.len();

      let framebuffer = Framebuffer::new((self.w, self.h), 0).unwrap();
      self.framebuffers.push(framebuffer);

      framebuffer_index
    })
  }

  /// Whenever a node has finished being composed, we *might* need to dispose the framebuffer it has
  /// pulled. This funciton does that job.
  ///
  /// It never deallocates memory. It has an important property: once a framebuffer is pulled,
  /// calling that function will make it available for other nodes, improving memory usage for the
  /// next calls.
  #[inline]
  fn dispose_framebuffer(&mut self, framebuffer_index: usize) {
    self.free_framebuffers.push(framebuffer_index);
  }

  /// Consume and display a compositing graph represented by its nodes.
  pub fn display(&mut self, root: Node) {
    let fb_index = self.treat_node(root);

    {
      let fb = &self.framebuffers[fb_index];

      let screen = Framebuffer::default((self.w, self.h));

      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
      let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[&*fb.color_slot];

      Pipeline::new(&screen, black, texture_set, &[], shd_cmd).run();
    }

    self.dispose_framebuffer(fb_index);
  }

  /// Treat a node hierarchy and return the index  of the framebuffer that contains the result.
  fn treat_node(&mut self, node: Node) -> usize {
    match node {
      Node::Render(layer) => self.render(layer),
      Node::Texture(texture) => self.texturize(texture),
      Node::Color(color) => self.colorize(color),
      Node::Composite(left, right, clear_color, eq, src_fct, dst_fct) => self.composite(*left, *right, clear_color, eq, src_fct, dst_fct),
    }
  }

  fn render(&mut self, layer: RenderLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    (layer.render)(&fb);

    fb_index
  }

  fn texturize(&mut self, texture: TextureLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let black = [0., 0., 0., 1.];
    let program = self.program.borrow();
    let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
    let tess_render = TessRender::from(&self.quad);
    let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
    let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
    let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
    let texture_set = &[&**texture];

    Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();

    fb_index
  }

  fn colorize(&mut self, color: ColorAlpha) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let color = *color.as_ref();

    Pipeline::new(fb, color, &[], &[], &[]).run();

    fb_index
  }

  fn composite(&mut self, left: Node, right: Node, clear_color: ColorAlpha, eq: Equation, src_fct: Factor, dst_fct: Factor) -> usize {
    let left_index = self.treat_node(left);
    let right_index = self.treat_node(right);

    assert!(left_index < self.framebuffers.len());
    assert!(right_index < self.framebuffers.len());

    let fb_index = self.pull_framebuffer();

    {
      let fb = &self.framebuffers[fb_index];

      let left_fb = &self.framebuffers[left_index];
      let right_fb = &self.framebuffers[right_index];

      // compose
      let program = self.program.borrow();
      let uniforms_left = [FORWARD_SOURCE.alter(Unit::new(0))];
      let uniforms_right = [FORWARD_SOURCE.alter(Unit::new(1))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[
        Pipe::empty().uniforms(&uniforms_left).unwrap(tess_render.clone()),
        Pipe::empty().uniforms(&uniforms_right).unwrap(tess_render)
      ];
      let render_cmd = &[Pipe::new(RenderCommand::new((eq, src_fct, dst_fct), false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[
        &*left_fb.color_slot,
        &*right_fb.color_slot
      ];

      Pipeline::new(fb, *clear_color.as_ref(), texture_set, &[], shd_cmd).run();
    }

    // dispose both left and right framebuffers
    self.dispose_framebuffer(left_index);
    self.dispose_framebuffer(right_index);

    fb_index
  }
}
<commit_msg>Fixed Node::over.<commit_after>use luminance::{Depth32F, Dim2, Flat, Framebuffer, Mode, RGBA32F, Tess, Texture, Uniform, Unit};
use luminance::pipeline::{Pipe, Pipeline, RenderCommand, ShadingCommand};
use luminance::tess::TessRender;
use std::ops::{Add, Mul, Sub};

pub use luminance::{Equation, Factor};

use color::ColorAlpha;
use resource::{Res, ResCache};
use shader::Program;

/// Simple texture that can be embedded into a compositing graph.
pub type TextureLayer<'a> = &'a ColorMap;

pub type ColorMap = Texture<Flat, Dim2, RGBA32F>;
pub type DepthMap = Texture<Flat, Dim2, Depth32F>;

/// Render layer used to host renders.
pub struct RenderLayer<'a> {
  render: Box<Fn(&Framebuffer<Flat, Dim2, ColorMap, DepthMap>) + 'a>
}

impl<'a> RenderLayer<'a> {
  pub fn new<F>(render: F) -> Self where F: 'a + Fn(&Framebuffer<Flat, Dim2, ColorMap, DepthMap>) {
    RenderLayer {
      render: Box::new(render)
    }
  }
}

/// Compositing node.
pub enum Node<'a> {
  /// A render node.
  ///
  /// Contains render layer.
  Render(RenderLayer<'a>),
  /// A texture node.
  ///
  /// Contains a single texture.
  Texture(TextureLayer<'a>),
  /// A single color.
  ///
  /// Keep in mind that such a node is great when you want to display a fullscreen colored quad but
  /// you shouldn’t use it for blending purpose. Adding color masking to your post-process is a
  /// better alternative and will avoid fillrate alteration.
  Color(ColorAlpha),
  /// Composite node.
  ///
  /// Composite nodes are used to blend two compositing nodes according to a given `Equation` and
  /// two blending `Factor`s for source and destination, respectively.
  Composite(Box<Node<'a>>, Box<Node<'a>>, ColorAlpha, Equation, Factor, Factor)
}

impl<'a> Node<'a> {
  /// Compose this node with another one.
  pub fn compose_with(self, rhs: Self, clear_color: ColorAlpha, eq: Equation, src_fct: Factor, dst_fct: Factor) -> Self {
    Node::Composite(Box::new(self), Box::new(rhs), clear_color, eq, src_fct, dst_fct)
  }

  /// Compose this node over the other. In effect, the resulting node will replace any pixels covered
  /// by the right node by the ones of the left node unless the alpha value is different than `1`.
  /// In that case, an additive blending based on the alpha value of the left node will be performed.
  ///
  /// If you set the alpha value to `0` at a pixel in the left node, then the resulting pixel will be
  /// the one from the right node.
  pub fn over(self, rhs: Self) -> Self {
    rhs.compose_with(self, ColorAlpha::new(0., 0., 0., 0.), Equation::Additive, Factor::SrcAlpha, Factor::SrcAlphaComplement)
  }
}

impl<'a> From<RenderLayer<'a>> for Node<'a> {
  fn from(layer: RenderLayer<'a>) -> Self {
    Node::Render(layer)
  }
}

impl<'a> From<TextureLayer<'a>> for Node<'a> {
  fn from(texture: TextureLayer<'a>) -> Self {
    Node::Texture(texture)
  }
}

impl<'a> From<ColorAlpha> for Node<'a> {
  fn from(color: ColorAlpha) -> Self {
    Node::Color(color)
  }
}

impl<'a> Add for Node<'a> {
  type Output = Self;

  fn add(self, rhs: Self) -> Self {
    self.compose_with(rhs, ColorAlpha::new(0., 0., 0., 0.), Equation::Additive, Factor::One, Factor::One)
  }
}

impl<'a> Sub for Node<'a> {
  type Output = Self;

  fn sub(self, rhs: Self) -> Self {
    self.compose_with(rhs, ColorAlpha::new(0., 0., 0., 0.), Equation::Subtract, Factor::One, Factor::One)
  }
}

impl<'a> Mul for Node<'a> {
  type Output = Self;

  fn mul(self, rhs: Self) -> Self {
    self.compose_with(rhs, ColorAlpha::new(1., 1., 1., 1.), Equation::Additive, Factor::Zero, Factor::SrcColor)
  }
}

/// Compositor object; used to consume `Node`s and output to screen.
pub struct Compositor {
  // width
  w: u32,
  // height
  h: u32,
  // allocated framebuffers that might contain nodes’ output
  framebuffers: Vec<Framebuffer<Flat, Dim2, ColorMap, DepthMap>>,
  // free list of available framebuffers
  free_framebuffers: Vec<usize>,
  // program used to compose nodes
  program: Res<Program>,
  // attributeless fullscreen quad for compositing
  quad: Tess
}

const FORWARD_SOURCE: &'static Uniform<Unit> = &Uniform::new(0);

impl Compositor {
  pub fn new(w: u32, h: u32, cache: &mut ResCache) -> Self {
    Compositor {
      w: w,
      h: h,
      framebuffers: Vec::new(),
      free_framebuffers: Vec::new(),
      program: cache.get("spectra/compositing/forward.glsl", vec![FORWARD_SOURCE.sem("source")]).unwrap(),
      quad: Tess::attributeless(Mode::TriangleStrip, 4)
    }
  }

  /// Whenever a node must be composed, we need a framebuffer to render into. This function pulls a
  /// framebuffer to use (via self.framebuffers) by returing an index. It might allocate a new
  /// framebuffer if there isn’t enough framebuffers to be pulled.
  fn pull_framebuffer(&mut self) -> usize {
    self.free_framebuffers.pop().unwrap_or_else(|| {
      let framebuffer_index = self.framebuffers.len();

      let framebuffer = Framebuffer::new((self.w, self.h), 0).unwrap();
      self.framebuffers.push(framebuffer);

      framebuffer_index
    })
  }

  /// Whenever a node has finished being composed, we *might* need to dispose the framebuffer it has
  /// pulled. This funciton does that job.
  ///
  /// It never deallocates memory. It has an important property: once a framebuffer is pulled,
  /// calling that function will make it available for other nodes, improving memory usage for the
  /// next calls.
  #[inline]
  fn dispose_framebuffer(&mut self, framebuffer_index: usize) {
    self.free_framebuffers.push(framebuffer_index);
  }

  /// Consume and display a compositing graph represented by its nodes.
  pub fn display(&mut self, root: Node) {
    let fb_index = self.treat_node(root);

    {
      let fb = &self.framebuffers[fb_index];

      let screen = Framebuffer::default((self.w, self.h));

      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
      let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[&*fb.color_slot];

      Pipeline::new(&screen, black, texture_set, &[], shd_cmd).run();
    }

    self.dispose_framebuffer(fb_index);
  }

  /// Treat a node hierarchy and return the index  of the framebuffer that contains the result.
  fn treat_node(&mut self, node: Node) -> usize {
    match node {
      Node::Render(layer) => self.render(layer),
      Node::Texture(texture) => self.texturize(texture),
      Node::Color(color) => self.colorize(color),
      Node::Composite(left, right, clear_color, eq, src_fct, dst_fct) => self.composite(*left, *right, clear_color, eq, src_fct, dst_fct),
    }
  }

  fn render(&mut self, layer: RenderLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    (layer.render)(&fb);

    fb_index
  }

  fn texturize(&mut self, texture: TextureLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let black = [0., 0., 0., 1.];
    let program = self.program.borrow();
    let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
    let tess_render = TessRender::from(&self.quad);
    let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
    let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
    let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
    let texture_set = &[&**texture];

    Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();

    fb_index
  }

  fn colorize(&mut self, color: ColorAlpha) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let color = *color.as_ref();

    Pipeline::new(fb, color, &[], &[], &[]).run();

    fb_index
  }

  fn composite(&mut self, left: Node, right: Node, clear_color: ColorAlpha, eq: Equation, src_fct: Factor, dst_fct: Factor) -> usize {
    let left_index = self.treat_node(left);
    let right_index = self.treat_node(right);

    assert!(left_index < self.framebuffers.len());
    assert!(right_index < self.framebuffers.len());

    let fb_index = self.pull_framebuffer();

    {
      let fb = &self.framebuffers[fb_index];

      let left_fb = &self.framebuffers[left_index];
      let right_fb = &self.framebuffers[right_index];

      // compose
      let program = self.program.borrow();
      let uniforms_left = [FORWARD_SOURCE.alter(Unit::new(0))];
      let uniforms_right = [FORWARD_SOURCE.alter(Unit::new(1))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[
        Pipe::empty().uniforms(&uniforms_left).unwrap(tess_render.clone()),
        Pipe::empty().uniforms(&uniforms_right).unwrap(tess_render)
      ];
      let render_cmd = &[Pipe::new(RenderCommand::new((eq, src_fct, dst_fct), false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[
        &*left_fb.color_slot,
        &*right_fb.color_slot
      ];

      Pipeline::new(fb, *clear_color.as_ref(), texture_set, &[], shd_cmd).run();
    }

    // dispose both left and right framebuffers
    self.dispose_framebuffer(left_index);
    self.dispose_framebuffer(right_index);

    fb_index
  }
}
<|endoftext|>


<commit_before>use std::io::{self};
use super::{Value, Tag, Vec2, Vec3, Vec4, Box2};

#[derive(PartialEq, Debug)]
pub enum Token {
    Start,
    End,
    Value(Value),
    EndOfFile
}

fn unexpected<T>(msg: &str) -> io::Result<T> {
    Err(io::Error::new(io::ErrorKind::InvalidData, msg))
}

pub trait Reader {
    fn read_next(&mut self) -> io::Result<Token>;

    fn skip_to_end(&mut self) -> io::Result<()> {
        let mut levels = 0;
        loop {
            match try!(self.read_next()) {
                Token::Value(_) => (),
                Token::Start => levels += 1,
                Token::End if levels == 0 => break,
                Token::End => levels -= 1,
                Token::EndOfFile if levels == 0 => break,
                Token::EndOfFile => return unexpected("Unexpected end of file")
            }
        }

        Ok(())
    }

    fn expect_start(&mut self) -> io::Result<()> {
        match try!(self.read_next()) {
            Token::Start => Ok(()),
            _ => unexpected("Expected start of group")
        }
    }

    fn expect_start_or_end(&mut self) -> io::Result<bool> {
        match try!(self.read_next()) {
            Token::Start => Ok(true),
            Token::End => Ok(false),
            Token::EndOfFile => Ok(false),
            _ => unexpected("Expected start or end of group")
        }
    }

    fn expect_tag(&mut self) -> io::Result<Tag> {
        match try!(self.read_next()) {
            Token::Value(Value::Tag(t)) => Ok(t),
            _ => unexpected("Expected tag")
        }
    }

    fn expect_bool(&mut self) -> io::Result<bool> {
        match try!(self.read_next()) {
            Token::Value(Value::Bool(b)) => Ok(b),
            _ => unexpected("Expected bool")
        }
    }

    fn expect_bool_array(&mut self) -> io::Result<Box<[bool]>> {
        match try!(self.read_next()) {
            Token::Value(Value::BoolArray(a)) => Ok(a),
            _ => unexpected("Expected bool array")
        }
    }

    fn expect_int(&mut self) -> io::Result<i32> {
        match try!(self.read_next()) {
            Token::Value(Value::Int(i)) => Ok(i),
            _ => unexpected("Expected int")
        }
    }

    fn expect_int_array(&mut self) -> io::Result<Box<[i32]>> {
        match try!(self.read_next()) {
            Token::Value(Value::IntArray(a)) => Ok(a),
            _ => unexpected("Expected int array")
        }
    }

    fn expect_double(&mut self) -> io::Result<f64> {
        match try!(self.read_next()) {
            Token::Value(Value::Double(d)) => Ok(d),
            _ => unexpected("Expected double")
        }
    }

    fn expect_double_array(&mut self) -> io::Result<Box<[f64]>> {
        match try!(self.read_next()) {
            Token::Value(Value::DoubleArray(a)) => Ok(a),
            _ => unexpected("Expected double array")
        }
    }

    fn expect_vec2(&mut self) -> io::Result<Vec2> {
        match try!(self.read_next()) {
            Token::Value(Value::Vec2(v)) => Ok(v),
            _ => unexpected("Expected vec2")
        }
    }

    fn expect_vec2_array(&mut self) -> io::Result<Box<[Vec2]>> {
        match try!(self.read_next()) {
            Token::Value(Value::Vec2Array(a)) => Ok(a),
            _ => unexpected("Expected vec2 array")
        }
    }

    fn expect_vec3(&mut self) -> io::Result<Vec3> {
        match try!(self.read_next()) {
            Token::Value(Value::Vec3(v)) => Ok(v),
            _ => unexpected("Expected vec3")
        }
    }

    fn expect_vec3_array(&mut self) -> io::Result<Box<[Vec3]>> {
        match try!(self.read_next()) {
            Token::Value(Value::Vec3Array(a)) => Ok(a),
            _ => unexpected("Expected vec3 array")
        }
    }

    fn expect_vec4(&mut self) -> io::Result<Vec4> {
        match try!(self.read_next()) {
            Token::Value(Value::Vec4(v)) => Ok(v),
            _ => unexpected("Expected vec4")
        }
    }

    fn expect_vec4_array(&mut self) -> io::Result<Box<[Vec4]>> {
        match try!(self.read_next()) {
            Token::Value(Value::Vec4Array(a)) => Ok(a),
            _ => unexpected("Expected vec4 array")
        }
    }

    fn expect_box2(&mut self) -> io::Result<Box2> {
        match try!(self.read_next()) {
            Token::Value(Value::Box2(b)) => Ok(b),
            _ => unexpected("Expected box2")
        }
    }

    fn expect_box2_array(&mut self) -> io::Result<Box<[Box2]>> {
        match try!(self.read_next()) {
            Token::Value(Value::Box2Array(a)) => Ok(a),
            _ => unexpected("Expected box2 array")
        }
    }

    fn expect_string(&mut self) -> io::Result<Box<str>> {
        match try!(self.read_next()) {
            Token::Value(Value::String(s)) => Ok(s),
            _ => unexpected("Expected string")
        }
    }

    fn expect_blob(&mut self) -> io::Result<Box<[u8]>> {
        match try!(self.read_next()) {
            Token::Value(Value::Blob(b)) => Ok(b),
            _ => unexpected("Expected blob")
        }
    }
}
<commit_msg>Add expect_*_or_end() fns to Reader<commit_after>use std::io::{self};
use super::{Value, Tag, Vec2, Vec3, Vec4, Box2};

#[derive(PartialEq, Debug)]
pub enum Token {
    Start,
    End,
    Value(Value),
    EndOfFile
}

fn unexpected<T>(msg: &str) -> io::Result<T> {
    Err(io::Error::new(io::ErrorKind::InvalidData, msg))
}

macro_rules! expect {
    ($_self:ident, $_enum:ident) => {
        match try!($_self.read_next()) {
            Token::Value(Value::$_enum(v)) => Ok(v),
            _ => unexpected(concat!("Expected ", stringify!($_enum)))
        }
    }
}

macro_rules! expect_or_end {
    ($_self:ident, $_enum:ident) => {
        match try!($_self.read_next()) {
            Token::Value(Value::$_enum(v)) => Ok(Some(v)),
            Token::End => Ok(None),
            _ => unexpected(concat!("Expected ", stringify!($_enum), " or end of group"))
        }
    }
}

pub trait Reader {
    fn read_next(&mut self) -> io::Result<Token>;

    fn skip_to_end(&mut self) -> io::Result<()> {
        let mut levels = 0;
        loop {
            match try!(self.read_next()) {
                Token::Value(_) => (),
                Token::Start => levels += 1,
                Token::End if levels == 0 => break,
                Token::End => levels -= 1,
                Token::EndOfFile if levels == 0 => break,
                Token::EndOfFile => return unexpected("Unexpected end of file")
            }
        }

        Ok(())
    }

    fn expect_start(&mut self) -> io::Result<()> {
        match try!(self.read_next()) {
            Token::Start => Ok(()),
            _ => unexpected("Expected start of group")
        }
    }

    fn expect_start_or_end(&mut self) -> io::Result<bool> {
        match try!(self.read_next()) {
            Token::Start => Ok(true),
            Token::End => Ok(false),
            Token::EndOfFile => Ok(false),
            _ => unexpected("Expected start or end of group")
        }
    }

    fn expect_tag(&mut self) -> io::Result<Tag> {
        expect!(self, Tag)
    }

    fn expect_tag_or_end(&mut self) -> io::Result<Option<Tag>> {
        expect_or_end!(self, Tag)
    }

    fn expect_bool(&mut self) -> io::Result<bool> {
        expect!(self, Bool)
    }

    fn expect_bool_or_end(&mut self) -> io::Result<Option<bool>> {
        expect_or_end!(self, Bool)
    }

    fn expect_bool_array(&mut self) -> io::Result<Box<[bool]>> {
        expect!(self, BoolArray)
    }

    fn expect_bool_array_or_end(&mut self) -> io::Result<Option<Box<[bool]>>> {
        expect_or_end!(self, BoolArray)
    }

    fn expect_int(&mut self) -> io::Result<i32> {
        expect!(self, Int)
    }

    fn expect_int_or_end(&mut self) -> io::Result<Option<i32>> {
        expect_or_end!(self, Int)
    }

    fn expect_int_array(&mut self) -> io::Result<Box<[i32]>> {
        expect!(self, IntArray)
    }

    fn expect_int_array_or_end(&mut self) -> io::Result<Option<Box<[i32]>>> {
        expect_or_end!(self, IntArray)
    }

    fn expect_double(&mut self) -> io::Result<f64> {
        expect!(self, Double)
    }

    fn expect_double_or_end(&mut self) -> io::Result<Option<f64>> {
        expect_or_end!(self, Double)
    }

    fn expect_double_array(&mut self) -> io::Result<Box<[f64]>> {
        expect!(self, DoubleArray)
    }

    fn expect_double_array_or_end(&mut self) -> io::Result<Option<Box<[f64]>>> {
        expect_or_end!(self, DoubleArray)
    }

    fn expect_vec2(&mut self) -> io::Result<Vec2> {
        expect!(self, Vec2)
    }

    fn expect_vec2_or_end(&mut self) -> io::Result<Option<Vec2>> {
        expect_or_end!(self, Vec2)
    }

    fn expect_vec2_array(&mut self) -> io::Result<Box<[Vec2]>> {
        expect!(self, Vec2Array)
    }

    fn expect_vec2_array_or_end(&mut self) -> io::Result<Option<Box<[Vec2]>>> {
        expect_or_end!(self, Vec2Array)
    }

    fn expect_vec3(&mut self) -> io::Result<Vec3> {
        expect!(self, Vec3)
    }

    fn expect_vec3_or_end(&mut self) -> io::Result<Option<Vec3>> {
        expect_or_end!(self, Vec3)
    }

    fn expect_vec3_array(&mut self) -> io::Result<Box<[Vec3]>> {
        expect!(self, Vec3Array)
    }

    fn expect_vec3_array_or_end(&mut self) -> io::Result<Option<Box<[Vec3]>>> {
        expect_or_end!(self, Vec3Array)
    }

    fn expect_vec4(&mut self) -> io::Result<Vec4> {
        expect!(self, Vec4)
    }

    fn expect_vec4_or_end(&mut self) -> io::Result<Option<Vec4>> {
        expect_or_end!(self, Vec4)
    }

    fn expect_vec4_array(&mut self) -> io::Result<Box<[Vec4]>> {
        expect!(self, Vec4Array)
    }

    fn expect_vec4_array_or_end(&mut self) -> io::Result<Option<Box<[Vec4]>>> {
        expect_or_end!(self, Vec4Array)
    }

    fn expect_box2(&mut self) -> io::Result<Box2> {
        expect!(self, Box2)
    }

    fn expect_box2_or_end(&mut self) -> io::Result<Option<Box2>> {
        expect_or_end!(self, Box2)
    }

    fn expect_box2_array(&mut self) -> io::Result<Box<[Box2]>> {
        expect!(self, Box2Array)
    }

    fn expect_box2_array_or_end(&mut self) -> io::Result<Option<Box<[Box2]>>> {
        expect_or_end!(self, Box2Array)
    }

    fn expect_string(&mut self) -> io::Result<Box<str>> {
        expect!(self, String)
    }

    fn expect_string_or_end(&mut self) -> io::Result<Option<Box<str>>> {
        expect_or_end!(self, String)
    }

    fn expect_blob(&mut self) -> io::Result<Box<[u8]>> {
        expect!(self, Blob)
    }
    fn expect_blob_or_end(&mut self) -> io::Result<Option<Box<[u8]>>> {
        expect_or_end!(self, Blob)
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct FsDirType {
    id: i32,
    name: String,
}

pub fn table_create_fs_dir_type(conn: &Connection)  -> &Connection {
    conn.execute("CREATE TABLE FS_DIR_TYPE (
                  id              INTEGER PRIMARY KEY ASC,
                  name            TEXT NOT NULL UNIQUE
                  )", &[]).unwrap();
    return conn;
}

pub fn insert_fs_dir_type(conn: &Connection, name: String) {

    let me = FsDirType {
        id: 0,
        name: name,
    };
    let load_instance = conn.execute("INSERT INTO FS_DIR_TYPE (name)
                  VALUES (?1)",
                 &[&me.name]);
    if load_instance.is_err() {
        return;
    }
    load_instance.unwrap();
}

pub fn list_fs_dir_type(conn: &Connection)-> Vec<FsDirType> {
    let mut stmt = conn.prepare("SELECT id, name FROM FS_DIR_TYPE").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        FsDirType {
            id: row.get(0),
            name: row.get(1),
        }
    });
    let mut items = Vec::<FsDirType>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}
<commit_msg>Normalising methods<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct FsDirType {
    id: i32,
    name: String,
}

pub fn table_create_fs_dir_type(conn: &Connection)  -> &Connection {
    conn.execute("CREATE TABLE FS_DIR_TYPE (
                  id              INTEGER PRIMARY KEY ASC,
                  name            TEXT NOT NULL UNIQUE
                  )", &[]).unwrap();
    return conn;
}

pub fn insert_fs_dir_type(conn: &Connection,  name: &String) -> Result<i32, &'static str> {
    let bill = name.clone();
    let me = FsDirType {
        id: 0,
        name: bill,
    };
    let provider_instance = conn.execute("INSERT INTO FS_DIR_TYPE (name)
                  VALUES (?1)",
                 &[&me.name]);
    if provider_instance.is_err() {
        return Err("Insert failed");
    }
    provider_instance.unwrap();
    return Ok(0);
}

pub fn list_fs_dir_type(conn: &Connection)-> Vec<FsDirType> {
    let mut stmt = conn.prepare("SELECT id, name FROM FS_DIR_TYPE").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        FsDirType {
            id: row.get(0),
            name: row.get(1),
        }
    });
    let mut items = Vec::<FsDirType>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn fs_dir_type_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, name  FROM FS_DIR_TYPE").unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        FsDirType {
            id: row.get(0),
            name: row.get(1),
        }
    }).unwrap();

    for person in person_iter {
        println!("Found fs_dir_type {:?}", person.unwrap());
    }
}

pub fn pk_fs_dir_type_by_name(conn: &Connection, name: &String, pk: &mut i32) -> Result<i32, &'static str>{
    let mut stmt = conn.prepare("SELECT id, name  FROM FS_DIR_TYPE WHERE name = ?1").unwrap();
    let variable_name_iter = stmt.query_map(&[name], |row| {
        FsDirType {
                id: row.get(0),
                name: row.get(1)
            }
    });
    if variable_name_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = variable_name_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill= person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}

<|endoftext|>


<commit_before>use std::fmt;

#[derive(Clone,Debug)]
pub enum HttpMethods {
    Get,
    Post,
}

impl fmt::Display for HttpMethods {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s: String = format!("{:?}", self);
        write!(f, "{}", s.to_uppercase())
    }
}

#[derive(Clone,Debug,PartialEq)]
pub enum ResponseCode {
    // Testing
    Undefined = 0,
    // Informational
    Continue = 100,
    SwitchingProtocols = 101,
    Processing = 102,
    // Success
    Ok = 200,
    Created = 201,
    Accepted = 202,
    NonAuthoritativeInformation = 203,
    NoContent = 204,
    ResetContent = 205,
    PartialContent = 206,
    MultiStatus = 207,
    AlreadyReported = 208,
    ImUsed = 226,
    // Redirection
    MultipleChoices = 300,
    MovedPermanently = 301,
    Found = 302,
    SeeOther = 303,
    NotModified = 304,
    UseProxy = 305,
    SwitchProxy = 306,
    TemporaryRedirect = 307,
    PermanentRedirect = 308,
    // Client Error
    BadRequest = 400,
    Unauthorized = 401,
    PaymentRequired = 402,
    Forbidden = 403,
    NotFound = 404,
    MethodNotAllowed = 405,
    NotAcceptable = 406,
    ProxyAuthenticationRequired = 407,
    RequestTimeout = 408,
    Conflict = 409,
    Gone = 410,
    LengthRequired = 411,
    PreconditionFailed = 412,
    PayloadTooLarge = 413,
    UriTooLong = 414,
    UnsupportedMediaType = 415,
    RangeNotSatisified = 416,
    ExpectationFailed = 417,
    ImATeapot = 418,
    MisdirectedRequest = 421,
    UnprocessableEntitiy = 422,
    Locked = 423,
    FailedDependency = 424,
    UpgradeRequired = 426,
    PreconditionRequired = 428,
    TooManyRequests = 429,
    RequestHeaderFieldsTooLarge = 431,
    UnavailableForLegalReasons = 451,
    // Server Error
    InternalServerError = 500,
    NotImplemented = 501,
    BadGateway = 502,
    ServiceUnavailable = 503,
    GatewayTimeout = 504,
    HttpVersionNotSupported = 505,
    VariantAlsoNegotiates = 506,
    InsufficientStorage = 507,
    LoopDetected = 508 ,
    NotExtended = 510,
    NetworkAuthenticationRequired = 511,
}

impl fmt::Display for ResponseCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s: String = format!("{:?}", self).to_owned();
        write!(f, "{}", &s.to_uppercase())
    }
}

impl ResponseCode {
    pub fn from_int(i: u32) -> ResponseCode {
        match i {
            // Testing
            0 => ResponseCode::Undefined,
            // Informational
            100 => ResponseCode::Continue,
            101 => ResponseCode::SwitchingProtocols,
            102 => ResponseCode::Processing,
            // Success
            200 => ResponseCode::Ok,
            201 => ResponseCode::Created,
            202 => ResponseCode::Accepted,
            203 => ResponseCode::NonAuthoritativeInformation,
            204 => ResponseCode::NoContent,
            205 => ResponseCode::ResetContent,
            206 => ResponseCode::PartialContent,
            207 => ResponseCode::MultiStatus,
            208 => ResponseCode::AlreadyReported,
            226 => ResponseCode::ImUsed,
            // Redirection
            300 => ResponseCode::MultipleChoices,
            301 => ResponseCode::MovedPermanently,
            302 => ResponseCode::Found,
            303 => ResponseCode::SeeOther,
            304 => ResponseCode::NotModified,
            305 => ResponseCode::UseProxy,
            306 => ResponseCode::SwitchProxy,
            307 => ResponseCode::TemporaryRedirect,
            308 => ResponseCode::PermanentRedirect,
            // Client Error
            400 => ResponseCode::BadRequest,
            401 => ResponseCode::Unauthorized,
            402 => ResponseCode::PaymentRequired,
            403 => ResponseCode::Forbidden,
            404 => ResponseCode::NotFound,
            405 => ResponseCode::MethodNotAllowed,
            406 => ResponseCode::NotAcceptable,
            407 => ResponseCode::ProxyAuthenticationRequired,
            408 => ResponseCode::RequestTimeout,
            409 => ResponseCode::Conflict,
            410 => ResponseCode::Gone,
            411 => ResponseCode::LengthRequired,
            412 => ResponseCode::PreconditionFailed,
            413 => ResponseCode::PayloadTooLarge,
            414 => ResponseCode::UriTooLong,
            415 => ResponseCode::UnsupportedMediaType,
            416 => ResponseCode::RangeNotSatisified,
            417 => ResponseCode::ExpectationFailed,
            418 => ResponseCode::ImATeapot,
            421 => ResponseCode::MisdirectedRequest,
            422 => ResponseCode::UnprocessableEntitiy,
            423 => ResponseCode::Locked,
            424 => ResponseCode::FailedDependency,
            426 => ResponseCode::UpgradeRequired,
            428 => ResponseCode::PreconditionRequired,
            429 => ResponseCode::TooManyRequests,
            431 => ResponseCode::RequestHeaderFieldsTooLarge,
            451 => ResponseCode::UnavailableForLegalReasons,
            // Server Error
            500 => ResponseCode::InternalServerError,
            501 => ResponseCode::NotImplemented,
            502 => ResponseCode::BadGateway,
            503 => ResponseCode::ServiceUnavailable,
            504 => ResponseCode::GatewayTimeout,
            505 => ResponseCode::HttpVersionNotSupported,
            506 => ResponseCode::VariantAlsoNegotiates,
            507 => ResponseCode::InsufficientStorage,
            508 => ResponseCode::LoopDetected,
            510 => ResponseCode::NotExtended,
            511 => ResponseCode::NetworkAuthenticationRequired,
            _ => ResponseCode::Undefined,
        }
    }

}

#[test]
pub fn methods_post() {
    let s = HttpMethods::Post.to_string();
    assert_eq!(s, "POST".to_owned());
}

#[test]
pub fn methods_get() {
    let s = HttpMethods::Get.to_string();
    assert_eq!(s, "GET".to_owned());
}

#[test]
pub fn response_code_success() {
    let s = ResponseCode::Continue.to_string();
    assert_eq!(s, "CONTINUE");
}
<commit_msg>eq on constants<commit_after>use std::fmt;

#[derive(Clone,Debug)]
pub enum HttpMethods {
    Get,
    Post,
}

impl fmt::Display for HttpMethods {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s: String = format!("{:?}", self);
        write!(f, "{}", s.to_uppercase())
    }
}

#[derive(Clone,Debug,PartialEq,Eq)]
pub enum ResponseCode {
    // Testing
    Undefined = 0,
    // Informational
    Continue = 100,
    SwitchingProtocols = 101,
    Processing = 102,
    // Success
    Ok = 200,
    Created = 201,
    Accepted = 202,
    NonAuthoritativeInformation = 203,
    NoContent = 204,
    ResetContent = 205,
    PartialContent = 206,
    MultiStatus = 207,
    AlreadyReported = 208,
    ImUsed = 226,
    // Redirection
    MultipleChoices = 300,
    MovedPermanently = 301,
    Found = 302,
    SeeOther = 303,
    NotModified = 304,
    UseProxy = 305,
    SwitchProxy = 306,
    TemporaryRedirect = 307,
    PermanentRedirect = 308,
    // Client Error
    BadRequest = 400,
    Unauthorized = 401,
    PaymentRequired = 402,
    Forbidden = 403,
    NotFound = 404,
    MethodNotAllowed = 405,
    NotAcceptable = 406,
    ProxyAuthenticationRequired = 407,
    RequestTimeout = 408,
    Conflict = 409,
    Gone = 410,
    LengthRequired = 411,
    PreconditionFailed = 412,
    PayloadTooLarge = 413,
    UriTooLong = 414,
    UnsupportedMediaType = 415,
    RangeNotSatisified = 416,
    ExpectationFailed = 417,
    ImATeapot = 418,
    MisdirectedRequest = 421,
    UnprocessableEntitiy = 422,
    Locked = 423,
    FailedDependency = 424,
    UpgradeRequired = 426,
    PreconditionRequired = 428,
    TooManyRequests = 429,
    RequestHeaderFieldsTooLarge = 431,
    UnavailableForLegalReasons = 451,
    // Server Error
    InternalServerError = 500,
    NotImplemented = 501,
    BadGateway = 502,
    ServiceUnavailable = 503,
    GatewayTimeout = 504,
    HttpVersionNotSupported = 505,
    VariantAlsoNegotiates = 506,
    InsufficientStorage = 507,
    LoopDetected = 508 ,
    NotExtended = 510,
    NetworkAuthenticationRequired = 511,
}

impl fmt::Display for ResponseCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s: String = format!("{:?}", self).to_owned();
        write!(f, "{}", &s.to_uppercase())
    }
}

impl ResponseCode {
    pub fn from_int(i: u32) -> ResponseCode {
        match i {
            // Testing
            0 => ResponseCode::Undefined,
            // Informational
            100 => ResponseCode::Continue,
            101 => ResponseCode::SwitchingProtocols,
            102 => ResponseCode::Processing,
            // Success
            200 => ResponseCode::Ok,
            201 => ResponseCode::Created,
            202 => ResponseCode::Accepted,
            203 => ResponseCode::NonAuthoritativeInformation,
            204 => ResponseCode::NoContent,
            205 => ResponseCode::ResetContent,
            206 => ResponseCode::PartialContent,
            207 => ResponseCode::MultiStatus,
            208 => ResponseCode::AlreadyReported,
            226 => ResponseCode::ImUsed,
            // Redirection
            300 => ResponseCode::MultipleChoices,
            301 => ResponseCode::MovedPermanently,
            302 => ResponseCode::Found,
            303 => ResponseCode::SeeOther,
            304 => ResponseCode::NotModified,
            305 => ResponseCode::UseProxy,
            306 => ResponseCode::SwitchProxy,
            307 => ResponseCode::TemporaryRedirect,
            308 => ResponseCode::PermanentRedirect,
            // Client Error
            400 => ResponseCode::BadRequest,
            401 => ResponseCode::Unauthorized,
            402 => ResponseCode::PaymentRequired,
            403 => ResponseCode::Forbidden,
            404 => ResponseCode::NotFound,
            405 => ResponseCode::MethodNotAllowed,
            406 => ResponseCode::NotAcceptable,
            407 => ResponseCode::ProxyAuthenticationRequired,
            408 => ResponseCode::RequestTimeout,
            409 => ResponseCode::Conflict,
            410 => ResponseCode::Gone,
            411 => ResponseCode::LengthRequired,
            412 => ResponseCode::PreconditionFailed,
            413 => ResponseCode::PayloadTooLarge,
            414 => ResponseCode::UriTooLong,
            415 => ResponseCode::UnsupportedMediaType,
            416 => ResponseCode::RangeNotSatisified,
            417 => ResponseCode::ExpectationFailed,
            418 => ResponseCode::ImATeapot,
            421 => ResponseCode::MisdirectedRequest,
            422 => ResponseCode::UnprocessableEntitiy,
            423 => ResponseCode::Locked,
            424 => ResponseCode::FailedDependency,
            426 => ResponseCode::UpgradeRequired,
            428 => ResponseCode::PreconditionRequired,
            429 => ResponseCode::TooManyRequests,
            431 => ResponseCode::RequestHeaderFieldsTooLarge,
            451 => ResponseCode::UnavailableForLegalReasons,
            // Server Error
            500 => ResponseCode::InternalServerError,
            501 => ResponseCode::NotImplemented,
            502 => ResponseCode::BadGateway,
            503 => ResponseCode::ServiceUnavailable,
            504 => ResponseCode::GatewayTimeout,
            505 => ResponseCode::HttpVersionNotSupported,
            506 => ResponseCode::VariantAlsoNegotiates,
            507 => ResponseCode::InsufficientStorage,
            508 => ResponseCode::LoopDetected,
            510 => ResponseCode::NotExtended,
            511 => ResponseCode::NetworkAuthenticationRequired,
            _ => ResponseCode::Undefined,
        }
    }

}

#[test]
pub fn methods_post() {
    let s = HttpMethods::Post.to_string();
    assert_eq!(s, "POST".to_owned());
}

#[test]
pub fn methods_get() {
    let s = HttpMethods::Get.to_string();
    assert_eq!(s, "GET".to_owned());
}

#[test]
pub fn response_code_success() {
    let s = ResponseCode::Continue.to_string();
    assert_eq!(s, "CONTINUE");
}
<|endoftext|>


<commit_before>use types::primitive::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct GetUpdates {
    pub offset: Option<Integer>,
    pub limit: Option<Integer>, // TODO(knsd): Values between 1—100 are accepted
    pub timeout: Option<Integer>, // TODO(knsd): Should be positive
    pub allowed_updates: Vec<AllowedUpdate> // TODO(knsd) BitSet? HashSet? BTreeSet?
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum AllowedUpdate {
    Message,
    EditedMessage,
    ChannelPost,
    EditedChannelPost,
//    InlineQuery,
//    ChosenInlineResult,
//    CallbackQuery,
}
<commit_msg>feat: implement Request for GetUpdates<commit_after>use requests::_base::*;
use types::primitive::*;
use types::update::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct GetUpdates {
    pub offset: Option<Integer>,
    pub limit: Option<Integer>, // TODO(knsd): Values between 1—100 are accepted
    pub timeout: Option<Integer>, // TODO(knsd): Should be positive
    pub allowed_updates: Vec<AllowedUpdate> // TODO(knsd) BitSet? HashSet? BTreeSet?
}

impl Request for GetUpdates {
    type Response = Vec<Update>;
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum AllowedUpdate {
    Message,
    EditedMessage,
    ChannelPost,
    EditedChannelPost,
//    InlineQuery,
//    ChosenInlineResult,
//    CallbackQuery,
}
<|endoftext|>


<commit_before>//! Internal, unsafe APIs for creating scoped tasks. Intended for
//! building abstractions atop the rayon-core thread pool, rather than
//! direct use by end users. These APIs are mostly analogous to the
//! (safe) `scope`/`spawn` APIs, but with some unsafe requirements
//! that permit greater efficiency.

use std::any::Any;
use std::sync::Arc;

/// Represents a task that can be scheduled onto the Rayon
/// thread-pool. Once a task is scheduler, it will execute exactly
/// once (eventually).
pub trait Task: Send + Sync {
    /// Invoked by the thread-pool when the task is ready to execute.
    fn execute(this: Arc<Self>);
}

/// Represents a handle onto some Rayon scope. This could be either a
/// local scope created by the `scope()` function or the global scope
/// for a thread-pool. To get a scope-handle, you can invoke
/// `ToScopeHandle::to_scope_handle()` on either a `scope` value or a
/// `ThreadPool`.
///
/// The existence of `ScopeHandler` offers a guarantee:
///
/// - The Rust lifetime `'scope` will not end until the scope-handle
///   is dropped, or until you invoke `panicked()` or `ok()`.
///
/// This trait is intended to be used as follows:
///
/// - You have a parallel task of type `T` to perform where `T: 's`,
///   meaning that any references that `T` contains outlive the lifetime
///   `'s`.
/// - You obtain a scope handle `h` of type `H` where `H:
///   ScopeHandle<'s>`; typically this would be by invoking
///   `to_scope_handle()` on a Rayon scope (of type `Scope<'s>`) or a
///   thread-pool (in which case `'s == 'static`).
/// - You invoke `h.spawn()` to start your job(s). This may be done
///   many times.
///   - Note that `h.spawn()` is an unsafe method. You must ensure
///     that your parallel jobs have completed before moving to
///     the next step.
/// - Eventually, when all invocations are complete, you invoke
///   either `panicked()` or `ok()`.
pub unsafe trait ScopeHandle<'scope>: 'scope {
    /// Enqueues a task for execution within the thread-pool. The task
    /// will eventually be invoked, and once it is, the `Arc` will be
    /// dropped.
    ///
    /// **Unsafe:** The caller must guarantee that the scope handle
    /// (`self`) will not be dropped (nor will `ok()` or `panicked()`
    /// be called) until the task executes. Otherwise, the lifetime
    /// `'scope` may end while the task is still pending.
    unsafe fn spawn_task<T: Task + 'scope>(&self, task: Arc<T>);

    /// Indicates that some sub-task of this scope panicked with the
    /// given `err`. This panic will be propagated back to the user as
    /// appropriate, depending on how this scope handle was derived.
    ///
    /// This takes ownership of the scope handle, meaning that once
    /// you invoke `panicked`, the scope is permitted to terminate
    /// (and, in particular, the Rust lifetime `'scope` may end).
    fn panicked(self, err: Box<Any + Send>);

    /// Indicates that the sub-tasks of this scope that you have
    /// spawned concluded successfully.
    ///
    /// This takes ownership of the scope handle, meaning that once
    /// you invoke `panicked`, the scope is permitted to terminate
    /// (and, in particular, the Rust lifetime `'scope` may end).
    fn ok(self);
}

/// Converts a Rayon structure (typicaly a `Scope` or `ThreadPool`)
/// into a "scope handle". See the `ScopeHandle` trait for more
/// details.
pub trait ToScopeHandle<'scope> {
    /// Scope handle type that gets produced.
    type ScopeHandle: ScopeHandle<'scope>;

    /// Convert the receiver into a scope handle.
    fn to_scope_handle(&self) -> Self::ScopeHandle;
}

<commit_msg>Fix typo in task.rs code-comment<commit_after>//! Internal, unsafe APIs for creating scoped tasks. Intended for
//! building abstractions atop the rayon-core thread pool, rather than
//! direct use by end users. These APIs are mostly analogous to the
//! (safe) `scope`/`spawn` APIs, but with some unsafe requirements
//! that permit greater efficiency.

use std::any::Any;
use std::sync::Arc;

/// Represents a task that can be scheduled onto the Rayon
/// thread-pool. Once a task is scheduler, it will execute exactly
/// once (eventually).
pub trait Task: Send + Sync {
    /// Invoked by the thread-pool when the task is ready to execute.
    fn execute(this: Arc<Self>);
}

/// Represents a handle onto some Rayon scope. This could be either a
/// local scope created by the `scope()` function or the global scope
/// for a thread-pool. To get a scope-handle, you can invoke
/// `ToScopeHandle::to_scope_handle()` on either a `scope` value or a
/// `ThreadPool`.
///
/// The existence of `ScopeHandler` offers a guarantee:
///
/// - The Rust lifetime `'scope` will not end until the scope-handle
///   is dropped, or until you invoke `panicked()` or `ok()`.
///
/// This trait is intended to be used as follows:
///
/// - You have a parallel task of type `T` to perform where `T: 's`,
///   meaning that any references that `T` contains outlive the lifetime
///   `'s`.
/// - You obtain a scope handle `h` of type `H` where `H:
///   ScopeHandle<'s>`; typically this would be by invoking
///   `to_scope_handle()` on a Rayon scope (of type `Scope<'s>`) or a
///   thread-pool (in which case `'s == 'static`).
/// - You invoke `h.spawn()` to start your job(s). This may be done
///   many times.
///   - Note that `h.spawn()` is an unsafe method. You must ensure
///     that your parallel jobs have completed before moving to
///     the next step.
/// - Eventually, when all invocations are complete, you invoke
///   either `panicked()` or `ok()`.
pub unsafe trait ScopeHandle<'scope>: 'scope {
    /// Enqueues a task for execution within the thread-pool. The task
    /// will eventually be invoked, and once it is, the `Arc` will be
    /// dropped.
    ///
    /// **Unsafe:** The caller must guarantee that the scope handle
    /// (`self`) will not be dropped (nor will `ok()` or `panicked()`
    /// be called) until the task executes. Otherwise, the lifetime
    /// `'scope` may end while the task is still pending.
    unsafe fn spawn_task<T: Task + 'scope>(&self, task: Arc<T>);

    /// Indicates that some sub-task of this scope panicked with the
    /// given `err`. This panic will be propagated back to the user as
    /// appropriate, depending on how this scope handle was derived.
    ///
    /// This takes ownership of the scope handle, meaning that once
    /// you invoke `panicked`, the scope is permitted to terminate
    /// (and, in particular, the Rust lifetime `'scope` may end).
    fn panicked(self, err: Box<Any + Send>);

    /// Indicates that the sub-tasks of this scope that you have
    /// spawned concluded successfully.
    ///
    /// This takes ownership of the scope handle, meaning that once
    /// you invoke `panicked`, the scope is permitted to terminate
    /// (and, in particular, the Rust lifetime `'scope` may end).
    fn ok(self);
}

/// Converts a Rayon structure (typically a `Scope` or `ThreadPool`)
/// into a "scope handle". See the `ScopeHandle` trait for more
/// details.
pub trait ToScopeHandle<'scope> {
    /// Scope handle type that gets produced.
    type ScopeHandle: ScopeHandle<'scope>;

    /// Convert the receiver into a scope handle.
    fn to_scope_handle(&self) -> Self::ScopeHandle;
}

<|endoftext|>


<commit_before>use libc::{c_int, c_longlong, c_char, c_void};
use std::mem;

/// Typedef for initialization function.
pub type EnergyMonInitFn = extern fn(*mut EnergyMon) -> c_int;
/// Typedef for read function.
pub type EnergyMonReadTotalFn = extern fn(*mut EnergyMon) -> c_longlong;
/// Typedef for cleanup function.
pub type EnergyMonFinishFn = extern fn(*mut EnergyMon) -> c_int;
/// Typedef for function to get human-readable name.
pub type EnergyMonGetSourceFn = extern fn(*mut c_char) -> *mut c_char;

#[repr(C)]
/// Representation of native C struct `em_impl`.
pub struct EnergyMon {
    /// Native C function type signature that initializes the `EnergyMon`.
    pub finit: EnergyMonInitFn,
    /// Native C function type signature that reads energy data from the `EnergyMon`.
    pub fread: EnergyMonReadTotalFn,
    /// Native C function type signature that cleans up the `EnergyMon`.
    pub ffinish: EnergyMonFinishFn,
    /// Native C function type signature that gets the `EnergyMon`'s human-readable name.
    pub fsource: EnergyMonGetSourceFn,
    /// Native C pointer used by the underlying `EnergyMon` implementation for storing state.
    pub state: *mut c_void,
}

extern {
    /// Native C function that fills in the EnergyMon struct values and may allocate other
    /// resources.
    fn em_impl_get(em: *mut EnergyMon) -> c_int;
}

impl EnergyMon {
    /// Create an `EnergyMon` which represents a C struct.
    pub fn new() -> Result<EnergyMon, &'static str> {
        unsafe {
            let mut em: EnergyMon = mem::uninitialized();
            let result: i32 = em_impl_get(&mut em);
            if result != 0 {
                return Err("Failed to create energymon");
            }
            Ok(em)
        }
    }

    /// Initialize the `EnergyMon` - may allocate more resources and/or start threads.
    pub fn init(&mut self) -> Result<(), &'static str> {
        let result: i32 = (self.finit)(self);
        if result != 0 {
            return Err("Failed to initialize energymon");
        }
        Ok(())
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&mut self) -> i64 {
        (self.fread)(self)
    }

    /// Cleanup the `EnergyMon` - may deallocate associated resources and/or stop threads.
    pub fn finish(&mut self) -> Result<(), &'static str> {
        let result: i32 = (self.ffinish)(self);
        if result != 0 {
            return Err("Failed to cleanup energymon");
        }
        Ok(())
    }

    /// Utility function to get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> Result<String, &'static str> {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return Err("Failed to get energymon source");
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        Ok(String::from_utf8_lossy(buf).into_owned())
    }
}

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

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        em.init().unwrap();
        let val = em.read();
        assert!(val >= 0);
        let source = em.source().unwrap();
        em.finish().unwrap();
        println!("Read {} from {}", val, source);
    }

}
<commit_msg>Add private EMImpl and wrap around that. Add initial attempt at SingletonEnergyMon<commit_after>use libc::{c_int, c_longlong, c_char, c_void};
use std::mem;
use std::sync::{Arc, Once, ONCE_INIT};
use std::cell::Cell;

/// Typedef for initialization function.
type EnergyMonInitFn = extern fn(*mut EMImpl) -> c_int;
/// Typedef for read function.
type EnergyMonReadTotalFn = extern fn(*mut EMImpl) -> c_longlong;
/// Typedef for cleanup function.
type EnergyMonFinishFn = extern fn(*mut EMImpl) -> c_int;
/// Typedef for function to get human-readable name.
type EnergyMonGetSourceFn = extern fn(*mut c_char) -> *mut c_char;

#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
#[repr(C)]
/// Representation of native C struct `em_impl`.
struct EMImpl {
    /// Native C function type signature that initializes the `EMImpl`.
    finit: EnergyMonInitFn,
    /// Native C function type signature that reads energy data from the `EMImpl`.
    fread: EnergyMonReadTotalFn,
    /// Native C function type signature that cleans up the `EMImpl`.
    ffinish: EnergyMonFinishFn,
    /// Native C function type signature that gets the `EMImpl`'s human-readable name.
    fsource: EnergyMonGetSourceFn,
    /// Native C pointer used by the underlying `EMImpl` implementation for storing state.
    state: *mut c_void,
}

extern {
    /// Native C function that fills in the EMImpl struct values and may allocate other resources.
    fn em_impl_get(em: *mut EMImpl) -> c_int;
}

impl EMImpl {
    /// Create an `EMImpl` which represents a C struct.
    fn new() -> Result<EMImpl, &'static str> {
        unsafe {
            let mut em: EMImpl = mem::uninitialized();
            match em_impl_get(&mut em) {
                0 => Ok(em),
                _ => Err("Failed to create EMImpl"),
            }
        }
    }

    /// Initialize the `EMImpl` - may allocate more resources and/or start threads.
    fn init(&mut self) -> Result<(), &'static str> {
        match (self.finit)(self) {
            0 => Ok(()),
            _ => Err("Failed to initialize EMImpl"),
        }
    }

    /// Read the total energy from the `EMImpl`.
    fn read(&mut self) -> i64 {
        (self.fread)(self)
    }

    /// Cleanup the `EMImpl` - may deallocate associated resources and/or stop threads.
    fn finish(&mut self) -> Result<(), &'static str> {
        match (self.ffinish)(self) {
            0 => Ok(()),
            _ => Err("Failed to cleanup EMImpl"),
        }
    }

    /// Utility function to get a human-readable name of the `EMImpl`'s source.
    fn source(&mut self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return "UNKNOWN".to_owned();
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        String::from_utf8_lossy(buf).into_owned()
    }
}

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: EMImpl,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
        println!("Initializing energy monitor");
        let mut em = try!{EMImpl::new()};
        try!{em.init()};
        Ok(EnergyMon { em: em })
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&mut self) -> i64 {
        self.em.read()
    }

    /// Get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> String {
        self.em.source()
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        println!("Finishing energy monitor");
        let _ = self.em.finish();
    }
}

#[derive(Clone)]
pub struct SingletonEnergyMon {
    em: Arc<Cell<EMImpl>>,
}

impl SingletonEnergyMon {
    pub fn instance() -> Option<SingletonEnergyMon> {
        static mut EM: *const SingletonEnergyMon = 0 as *const SingletonEnergyMon;
        static ONCE: Once = ONCE_INIT;

        unsafe {
            ONCE.call_once(|| {
                println!("Initializing singleton energy monitor");
                let mut em = match EMImpl::new() {
                    Ok(e) => e,
                    Err(e) => {
                        println!("{}", e);
                        return;
                    },
                };
                match em.init() {
                    Ok(_) => (),
                    Err(e) => {
                        println!("{}", e);
                        let _ = em.finish();
                        return;
                    },
                }
                let sem: SingletonEnergyMon = SingletonEnergyMon {
                    em: Arc::new(Cell::new(em))
                };
                // put it on the heap
                EM = mem::transmute(Box::new(sem));
            });
            Some((*EM).clone())
        }
    }

    pub fn read(&self) -> i64 {
        self.em.get().read()
    }

    pub fn source(&self) -> String {
        self.em.get().source()
    }

    pub unsafe fn destroy(&self) {
        println!("Finishing singleton energy monitor");
        let _ = self.em.get().finish();
    }
}

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

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read();
        assert!(val >= 0);
        println!("Read {} from {}", val, em.source());
    }

    #[test]
    fn test_singleton() {
        for _ in 0..2 {
            let sem: SingletonEnergyMon = SingletonEnergyMon::instance().unwrap();
            let val = sem.read();
            println!("Read {} from {} singleton", val, sem.source());
        }
        unsafe {
            SingletonEnergyMon::instance().unwrap().destroy();
        }
    }

}
<|endoftext|>


<commit_before>use sass::value_part::ValuePart;

use std::borrow::Cow::Borrowed;
use std::collections::HashMap;

pub fn evaluate(original: &str, variables: &HashMap<String, String>) -> String {
    let mut vt = ValueTokenizer::new(original);
    let mut value_stack = Vec::new();
    let mut op_stack = Vec::new();

    while let Some(part) = vt.next() {
        match part {
            ValuePart::Variable(name) => {
                match (*variables).get(&(*name).to_string()) {
                    Some(v) => value_stack.push(ValuePart::String(Borrowed(v))),
                    None => value_stack.push(ValuePart::String(name)),
                }
            },
            s @ ValuePart::String(..) => value_stack.push(s),
            n @ ValuePart::Number(..) => value_stack.push(n),
            o @ ValuePart::Operator(..) => op_stack.push(o),
        }
    }

    while let Some(ValuePart::Operator(current_op)) = op_stack.pop() {
        let second = value_stack.pop().unwrap();
        let first  = value_stack.pop().unwrap();
        value_stack.push(current_op.apply(first, second));
    }

    value_stack.into_iter().map(|v| v.to_string()).collect::<Vec<_>>().join(" ")
}

fn isnt_space(c: u8) -> bool {
    c != b' '
}

fn is_number(c: u8) -> bool {
    let result = match c {
        b'0' ... b'9' | b'.' => true,
        _ => false,
    };
    result
}

fn is_operator(c: u8) -> bool {
    match c {
        b'+' | b'-' | b'*' | b'/' | b'%' | b'(' | b')' | b',' => true,
        _ => false,
    }
}

#[derive(Debug)]
pub struct ValueTokenizer<'a> {
    value_str: &'a str,
    bytes: &'a [u8],
    offset: usize,
}

impl<'a> ValueTokenizer<'a> {
    pub fn new(value_str: &'a str) -> ValueTokenizer<'a> {
        ValueTokenizer {
            value_str: &value_str,
            bytes: &value_str.as_bytes(),
            offset: 0,
        }
    }

    pub fn parse(&mut self) -> Option<ValuePart<'a>> {
        let start = self.offset;
        let mut i = self.offset;
        let limit = self.value_str.len();

        if is_operator(self.bytes[start]) {
            self.offset = start + 2;
            Some(ValuePart::Operator(self.value_str[start..start + 1].parse().unwrap()))
        } else if is_number(self.bytes[start]) {
            i += self.scan_while(&self.value_str[i..limit], is_number);
            self.offset = i + 1;
            Some(ValuePart::Number(self.value_str[start..i].parse().unwrap()))
        } else if self.bytes[start] == b'$' {
            i += self.scan_while(&self.value_str[i..limit], isnt_space);
            self.offset = i + 1;
            Some(ValuePart::Variable(Borrowed(&self.value_str[start..i])))
        } else {
            i += self.scan_while(&self.value_str[i..limit], isnt_space);
            self.offset = i + 1;
            Some(ValuePart::String(Borrowed(&self.value_str[start..i])))
        }
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

}

impl<'a> Iterator for ValueTokenizer<'a> {
    type Item = ValuePart<'a>;

    fn next(&mut self) -> Option<ValuePart<'a>> {
        if self.offset < self.value_str.len() {
            return self.parse()
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sass::value_part::ValuePart;
    use sass::op::Op;
    use std::borrow::Cow::Borrowed;
    use std::collections::HashMap;

    #[test]
    fn it_returns_string_part() {
        let mut vt = ValueTokenizer::new("foo");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_space_separated_string_parts() {
        let mut vt = ValueTokenizer::new("foo bar");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"bar"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variable() {
        let mut vt = ValueTokenizer::new("$foo");
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variables_and_string_parts() {
        let mut vt = ValueTokenizer::new("foo $bar baz $quux");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$bar"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"baz"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$quux"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_number() {
        let mut vt = ValueTokenizer::new("3");
        assert_eq!(Some(ValuePart::Number(3.0)), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_two_numbers() {
        let mut vt = ValueTokenizer::new("3 8.9");
        assert_eq!(Some(ValuePart::Number(3.0)), vt.next());
        assert_eq!(Some(ValuePart::Number(8.9)), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_operator() {
        let mut vt = ValueTokenizer::new("+");
        assert_eq!(Some(ValuePart::Operator(Op::Plus)), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_numbers_and_operators() {
        let mut vt = ValueTokenizer::new("6 + 75.2");
        assert_eq!(Some(ValuePart::Number(6.0)), vt.next());
        assert_eq!(Some(ValuePart::Operator(Op::Plus)), vt.next());
        assert_eq!(Some(ValuePart::Number(75.2)), vt.next());
        assert_eq!(None, vt.next());
    }

    // evaluate tests =====================

    #[test]
    fn it_subtitutes_variable_values() {
        let mut vars = HashMap::new();
        vars.insert("$bar".to_string(), "4".to_string());
        vars.insert("$quux".to_string(), "3px 10px".to_string());

        let answer = evaluate("foo $bar 199.82 baz $quux", &vars);
        assert_eq!("foo 4 199.82 baz 3px 10px", answer);
    }

    #[test]
    fn it_adds() {
        let answer = evaluate("1 + 2", &HashMap::new());
        assert_eq!("3", answer);
    }
}
<commit_msg>Don't assume there will be spaces between value parts<commit_after>use sass::value_part::ValuePart;

use std::borrow::Cow::Borrowed;
use std::collections::HashMap;

pub fn evaluate(original: &str, variables: &HashMap<String, String>) -> String {
    let mut vt = ValueTokenizer::new(original);
    let mut value_stack = Vec::new();
    let mut op_stack = Vec::new();

    while let Some(part) = vt.next() {
        match part {
            ValuePart::Variable(name) => {
                match (*variables).get(&(*name).to_string()) {
                    Some(v) => value_stack.push(ValuePart::String(Borrowed(v))),
                    None => value_stack.push(ValuePart::String(name)),
                }
            },
            s @ ValuePart::String(..) => value_stack.push(s),
            n @ ValuePart::Number(..) => value_stack.push(n),
            o @ ValuePart::Operator(..) => op_stack.push(o),
        }
    }

    while let Some(ValuePart::Operator(current_op)) = op_stack.pop() {
        let second = value_stack.pop().unwrap();
        let first  = value_stack.pop().unwrap();
        value_stack.push(current_op.apply(first, second));
    }

    value_stack.into_iter().map(|v| v.to_string()).collect::<Vec<_>>().join(" ")
}

fn is_space(c: u8) -> bool {
    c == b' '
}

fn isnt_space(c: u8) -> bool {
    !is_space(c)
}

fn is_number(c: u8) -> bool {
    let result = match c {
        b'0' ... b'9' | b'.' => true,
        _ => false,
    };
    result
}

fn is_operator(c: u8) -> bool {
    match c {
        b'+' | b'-' | b'*' | b'/' | b'%' | b'(' | b')' | b',' => true,
        _ => false,
    }
}

#[derive(Debug)]
pub struct ValueTokenizer<'a> {
    value_str: &'a str,
    bytes: &'a [u8],
    offset: usize,
}

impl<'a> ValueTokenizer<'a> {
    pub fn new(value_str: &'a str) -> ValueTokenizer<'a> {
        ValueTokenizer {
            value_str: &value_str,
            bytes: &value_str.as_bytes(),
            offset: 0,
        }
    }

    pub fn parse(&mut self) -> Option<ValuePart<'a>> {
        self.skip_leading_whitespace();

        let start = self.offset;
        let mut i = self.offset;
        let limit = self.value_str.len();

        if is_operator(self.bytes[start]) {
            self.offset = start + 1;
            Some(ValuePart::Operator(self.value_str[start..start + 1].parse().unwrap()))
        } else if is_number(self.bytes[start]) {
            i += self.scan_while(&self.value_str[i..limit], is_number);
            self.offset = i;
            Some(ValuePart::Number(self.value_str[start..i].parse().unwrap()))
        } else if self.bytes[start] == b'$' {
            i += self.scan_while(&self.value_str[i..limit], isnt_space);
            self.offset = i;
            Some(ValuePart::Variable(Borrowed(&self.value_str[start..i])))
        } else {
            i += self.scan_while(&self.value_str[i..limit], isnt_space);
            self.offset = i;
            Some(ValuePart::String(Borrowed(&self.value_str[start..i])))
        }
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
       let mut i = self.offset;
       let limit = self.value_str.len();

       while i < limit {
           let c = self.bytes[i];
           if is_space(c) {
               i += self.scan_while(&self.value_str[i..limit], is_space);
           } else {
               self.offset = i;
               return
           }
       }
       self.offset = limit;
   }
}

impl<'a> Iterator for ValueTokenizer<'a> {
    type Item = ValuePart<'a>;

    fn next(&mut self) -> Option<ValuePart<'a>> {
        if self.offset < self.value_str.len() {
            return self.parse()
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sass::value_part::ValuePart;
    use sass::op::Op;
    use std::borrow::Cow::Borrowed;
    use std::collections::HashMap;

    #[test]
    fn it_returns_string_part() {
        let mut vt = ValueTokenizer::new("foo");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_space_separated_string_parts() {
        let mut vt = ValueTokenizer::new("foo bar");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"bar"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variable() {
        let mut vt = ValueTokenizer::new("$foo");
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variables_and_string_parts() {
        let mut vt = ValueTokenizer::new("foo $bar baz $quux");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$bar"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"baz"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$quux"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_number() {
        let mut vt = ValueTokenizer::new("3");
        assert_eq!(Some(ValuePart::Number(3.0)), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_two_numbers() {
        let mut vt = ValueTokenizer::new("3 8.9");
        assert_eq!(Some(ValuePart::Number(3.0)), vt.next());
        assert_eq!(Some(ValuePart::Number(8.9)), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_operator() {
        let mut vt = ValueTokenizer::new("+");
        assert_eq!(Some(ValuePart::Operator(Op::Plus)), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_numbers_and_operators() {
        let mut vt = ValueTokenizer::new("6 + 75.2");
        assert_eq!(Some(ValuePart::Number(6.0)), vt.next());
        assert_eq!(Some(ValuePart::Operator(Op::Plus)), vt.next());
        assert_eq!(Some(ValuePart::Number(75.2)), vt.next());
        assert_eq!(None, vt.next());
    }

    // evaluate tests =====================

    #[test]
    fn it_subtitutes_variable_values() {
        let mut vars = HashMap::new();
        vars.insert("$bar".to_string(), "4".to_string());
        vars.insert("$quux".to_string(), "3px 10px".to_string());

        let answer = evaluate("foo $bar 199.82 baz $quux", &vars);
        assert_eq!("foo 4 199.82 baz 3px 10px", answer);
    }

    #[test]
    fn it_adds() {
        let answer = evaluate("1 + 2", &HashMap::new());
        assert_eq!("3", answer);
    }

    #[test]
    fn it_doesnt_need_space_around_operators() {
        let answer = evaluate("12*4", &HashMap::new());
        assert_eq!("48", answer);
    }

}
<|endoftext|>


<commit_before>use bit_vec::BitVec;
use std::slice::Iter;
use lfsr;

#[derive(PartialEq, Debug)]
pub struct FibonacciLFSR {
    state: BitVec,
    taps: Vec<usize>,
}

impl FibonacciLFSR {
    pub fn from_iter(iter: Iter<usize>) -> Self {
        let &len = iter.clone().max().unwrap();

        let state = BitVec::from_elem(len, true);

        let mut taps: Vec<usize> = iter.map(|&t| t).collect();
        taps.sort();
        taps.dedup();

        FibonacciLFSR { state: state, taps: taps, }
    }

    fn shift(&mut self) {
        lfsr::shift(&mut self.state);
    }

    fn feedback_bit(&mut self) -> bool {
        self.taps
            .iter()
            .map(|&i| self.state[i - 1])
            .fold(false, |acc, b| acc ^ b)
    }

    pub fn iter(&mut self) -> lfsr::LFSRIter<FibonacciLFSR> {
        lfsr::LFSRIter { lfsr: self }
    }
}

impl lfsr::LFSR for FibonacciLFSR {
    fn output(&self) -> bool {
        let len = self.state.len();
        self.state[len - 1]
    }

    fn step(&mut self) {
        let b = self.feedback_bit();

        self.shift();

        self.state.set(0, b);
    }
}
<commit_msg>Add IntoIterator impls for FibonacciLFSR<commit_after>use bit_vec::BitVec;
use std::slice::Iter;
use lfsr;

#[derive(PartialEq, Debug)]
pub struct FibonacciLFSR {
    state: BitVec,
    taps: Vec<usize>,
}

impl FibonacciLFSR {
    pub fn from_iter(iter: Iter<usize>) -> Self {
        let &len = iter.clone().max().unwrap();

        let state = BitVec::from_elem(len, true);

        let mut taps: Vec<usize> = iter.map(|&t| t).collect();
        taps.sort();
        taps.dedup();

        FibonacciLFSR { state: state, taps: taps, }
    }

    fn shift(&mut self) {
        lfsr::shift(&mut self.state);
    }

    fn feedback_bit(&mut self) -> bool {
        self.taps
            .iter()
            .map(|&i| self.state[i - 1])
            .fold(false, |acc, b| acc ^ b)
    }

    pub fn iter(&mut self) -> lfsr::Iter<FibonacciLFSR> {
        lfsr::Iter { lfsr: self }
    }
}

impl lfsr::LFSR for FibonacciLFSR {
    fn output(&self) -> bool {
        let len = self.state.len();
        self.state[len - 1]
    }

    fn step(&mut self) {
        let b = self.feedback_bit();

        self.shift();

        self.state.set(0, b);
    }
}

impl IntoIterator for FibonacciLFSR {
    type Item = bool;
    type IntoIter = lfsr::IntoIter<FibonacciLFSR>;

    fn into_iter(self) -> Self::IntoIter {
        lfsr::IntoIter { lfsr: self }
    }
}

impl<'a> IntoIterator for &'a mut FibonacciLFSR {
    type Item = bool;
    type IntoIter = lfsr::Iter<'a, FibonacciLFSR>;

    fn into_iter(self) -> Self::IntoIter {
        lfsr::Iter { lfsr: self }
    }
}
<|endoftext|>